{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "organization",
  "title": "Organization",
  "description": "Organization plugin: multi-tenant organization management with members, invitations, and roles. Registers direct invitation acceptance, an organizations settings tab, a full `<Organization />` shell, and an `<OrganizationSwitcher />` dropdown.",
  "dependencies": [
    "@better-auth-ui/react@latest",
    "@better-auth-ui/core@latest",
    "@tanstack/react-pacer",
    "better-auth",
    "lucide-react"
  ],
  "registryDependencies": [
    "alert-dialog",
    "avatar",
    "badge",
    "button",
    "card",
    "dialog",
    "dropdown-menu",
    "empty",
    "field",
    "input",
    "input-group",
    "item",
    "label",
    "select",
    "separator",
    "skeleton",
    "sonner",
    "spinner",
    "table",
    "tabs",
    "https://better-auth-ui.com/r/radix-nova/user-view.json"
  ],
  "files": [
    {
      "path": "src/lib/auth/auth-plugin.ts",
      "content": "import type {\n  AuthPluginComponents,\n  AuthPlugin as AuthPluginPrimitive\n} from \"@better-auth-ui/react\"\n\ndeclare module \"@better-auth-ui/core\" {\n  /** Widens `useAuth().plugins` to the shadcn-typed `AuthPlugin`. */\n  interface AuthPluginRegister {\n    shadcn: AuthPlugin\n  }\n}\n\n/** Props the shadcn `<Auth>` router spreads onto plugin-contributed auth views. */\nexport type AuthViewProps = {\n  className?: string\n  socialLayout?: \"auto\" | \"horizontal\" | \"vertical\" | \"grid\"\n  socialPosition?: \"top\" | \"bottom\"\n}\n\n/** Props the shadcn `<Settings>` router spreads onto plugin-contributed settings views. */\nexport type SettingsViewProps = {\n  className?: string\n}\n\n/** Shadcn plugin type. Plugin authors import this from `@/lib/auth/auth-plugin`. */\nexport type AuthPlugin = AuthPluginPrimitive<\n  AuthPluginComponents,\n  AuthViewProps,\n  SettingsViewProps\n>\n",
      "type": "registry:lib",
      "target": "@lib/auth/auth-plugin.ts"
    },
    {
      "path": "src/lib/auth/organization-plugin.tsx",
      "content": "import { createAuthPlugin } from \"@better-auth-ui/core\"\nimport {\n  organizationPlugin as coreOrganizationPlugin,\n  type OrganizationLocalization,\n  type OrganizationPluginOptions\n} from \"@better-auth-ui/core/plugins\"\nimport { Briefcase } from \"lucide-react\"\n\nimport { AcceptInvitation } from \"@/components/auth/organization/accept-invitation\"\nimport { OrganizationsSettings } from \"@/components/auth/organization/organizations-settings\"\n\nexport const organizationPlugin = createAuthPlugin(\n  coreOrganizationPlugin.id,\n  (options: OrganizationPluginOptions = {}) => {\n    const core = coreOrganizationPlugin(options)\n\n    return {\n      ...core,\n      localization: core.localization as OrganizationLocalization,\n      views: {\n        auth: { acceptInvitation: AcceptInvitation }\n      },\n      settingsTabs: [\n        {\n          view: \"organizations\",\n          label: (\n            <>\n              <Briefcase className=\"text-muted-foreground\" />\n              {core.localization.organizations}\n            </>\n          ),\n          component: OrganizationsSettings\n        }\n      ]\n    }\n  }\n)\n",
      "type": "registry:lib",
      "target": "@lib/auth/organization-plugin.tsx"
    },
    {
      "path": "src/components/auth/organization/accept-invitation.tsx",
      "content": "\"use client\"\n\nimport { getSafeRedirectTo } from \"@better-auth-ui/core\"\nimport {\n  type OrganizationAuthClient,\n  useAcceptInvitation,\n  useAuth,\n  useAuthenticate,\n  useAuthPlugin,\n  useInvitation,\n  useRejectInvitation\n} from \"@better-auth-ui/react\"\nimport type { Invitation } from \"better-auth/client\"\nimport { BriefcaseBusiness, Check, X } from \"lucide-react\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\"\nimport { FieldDescription } from \"@/components/ui/field\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { useIsHydrated } from \"../use-is-hydrated\"\n\ntype UserInvitation = Invitation & { organizationName?: string }\n\nexport type AcceptInvitationProps = {\n  className?: string\n}\n\nfunction isPendingInvitation(invitation: UserInvitation | undefined) {\n  if (invitation?.status !== \"pending\") return false\n\n  return new Date(invitation.expiresAt).getTime() > Date.now()\n}\n\n/**\n * Render the organization invitation addressed by the `invitationId` query\n * parameter and let the signed-in recipient accept or reject it directly.\n */\nexport function AcceptInvitation({ className }: AcceptInvitationProps) {\n  const { authClient, navigate, redirectTo } = useAuth()\n  const { localization, roles } = useAuthPlugin(organizationPlugin)\n  const organizationAuthClient = authClient as OrganizationAuthClient\n  const isHydrated = useIsHydrated()\n  const invitationId = isHydrated\n    ? new URLSearchParams(window.location.search).get(\"invitationId\")\n    : null\n  const session = useAuthenticate(organizationAuthClient)\n  const invitationQuery = useInvitation(organizationAuthClient, {\n    query: { id: invitationId ?? \"\" },\n    enabled: Boolean(invitationId)\n  })\n  const invitation = invitationQuery.data as UserInvitation | undefined\n\n  const returnToApplication = () => {\n    navigate({\n      to: getSafeRedirectTo(redirectTo, window.location.origin),\n      replace: true\n    })\n  }\n\n  const { mutate: acceptInvitation, isPending: isAccepting } =\n    useAcceptInvitation(organizationAuthClient, {\n      onSuccess: returnToApplication\n    })\n  const { mutate: rejectInvitation, isPending: isRejecting } =\n    useRejectInvitation(organizationAuthClient, {\n      onSuccess: returnToApplication\n    })\n  const isLoading =\n    !isHydrated ||\n    session.isPending ||\n    !session.data ||\n    (Boolean(invitationId) && invitationQuery.isPending)\n  const isAvailable = isPendingInvitation(invitation)\n  const organizationName =\n    invitation?.organizationName || localization.organization\n  const role = invitation\n    ? (roles?.[invitation.role] ?? invitation.role)\n    : localization.member\n\n  return (\n    <Card className={cn(\"w-full max-w-sm\", className)}>\n      <CardHeader className=\"gap-3\">\n        <div className=\"flex size-10 items-center justify-center rounded-md bg-muted\">\n          <BriefcaseBusiness className=\"size-5\" />\n        </div>\n\n        <CardTitle className=\"text-xl font-semibold\">\n          {isLoading ? (\n            <Skeleton className=\"h-6 w-48\" />\n          ) : isAvailable ? (\n            localization.acceptInvitationTitle\n          ) : (\n            localization.invitationUnavailable\n          )}\n        </CardTitle>\n      </CardHeader>\n\n      <CardContent className=\"flex flex-col gap-4\">\n        {isLoading ? (\n          <div className=\"flex flex-col gap-2\">\n            <Skeleton className=\"h-4 w-full\" />\n            <Skeleton className=\"h-4 w-3/4\" />\n          </div>\n        ) : isAvailable ? (\n          <>\n            <FieldDescription>\n              {localization.acceptInvitationDescription\n                .replace(\"{{organization}}\", organizationName)\n                .replace(\"{{role}}\", role)}\n            </FieldDescription>\n\n            <div className=\"flex items-center gap-3 rounded-md bg-muted p-3\">\n              <div className=\"min-w-0 flex-1 truncate text-sm font-medium\">\n                {organizationName}\n              </div>\n              <Badge variant=\"secondary\">{role}</Badge>\n            </div>\n          </>\n        ) : (\n          <FieldDescription>\n            {localization.invitationUnavailableDescription}\n          </FieldDescription>\n        )}\n\n        <div className=\"flex gap-2\">\n          {isLoading ? (\n            <>\n              <Skeleton className=\"h-9 flex-1\" />\n              <Skeleton className=\"h-9 flex-1\" />\n            </>\n          ) : isAvailable && invitation ? (\n            <>\n              <Button\n                className=\"flex-1\"\n                type=\"button\"\n                variant=\"outline\"\n                disabled={isAccepting || isRejecting}\n                onClick={() =>\n                  rejectInvitation({ invitationId: invitation.id })\n                }\n              >\n                {isRejecting ? <Spinner /> : <X />}\n                {localization.rejectInvitation}\n              </Button>\n\n              <Button\n                className=\"flex-1\"\n                type=\"button\"\n                disabled={isAccepting || isRejecting}\n                onClick={() =>\n                  acceptInvitation({ invitationId: invitation.id })\n                }\n              >\n                {isAccepting ? <Spinner /> : <Check />}\n                {localization.accept}\n              </Button>\n            </>\n          ) : (\n            <Button\n              className=\"w-full\"\n              type=\"button\"\n              onClick={returnToApplication}\n            >\n              {localization.return}\n            </Button>\n          )}\n        </div>\n      </CardContent>\n    </Card>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/accept-invitation.tsx"
    },
    {
      "path": "src/components/auth/use-is-hydrated.ts",
      "content": "\"use client\"\n\nimport { useSyncExternalStore } from \"react\"\n\n/**\n * Returns `true` once the component is mounted on the client (hydrated) and\n * `false` while rendering on the server, so client-only reads (e.g.\n * `sessionStorage`) stay safe during SSR.\n *\n * @returns Whether the component has hydrated on the client.\n */\nexport function useIsHydrated() {\n  const subscribe = () => () => {}\n  return useSyncExternalStore(\n    subscribe,\n    () => true,\n    () => false\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/use-is-hydrated.ts"
    },
    {
      "path": "src/components/auth/organization/organization.tsx",
      "content": "\"use client\"\n\nimport type { OrganizationView } from \"@better-auth-ui/core/plugins\"\nimport {\n  type OrganizationAuthClient,\n  useActiveOrganization,\n  useAuth,\n  useAuthenticate,\n  useAuthPlugin\n} from \"@better-auth-ui/react\"\nimport { Settings as SettingsIcon, User2 as UserIcon } from \"lucide-react\"\nimport { useEffect, useMemo } from \"react\"\n\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { OrganizationPeople } from \"./organization-people\"\nimport { OrganizationSettings } from \"./organization-settings\"\n\nexport type OrganizationProps = {\n  className?: string\n  hideNav?: boolean\n  path?: string\n  /** @remarks `OrganizationView` */\n  view?: OrganizationView\n}\n\n/**\n * Organization management shell: tabs for profile / danger zone and for\n * people (members / invitations). Path segments come from\n * `useAuthPlugin(organizationPlugin).viewPaths.organization`.\n */\nexport function Organization({\n  className,\n  hideNav,\n  path,\n  view\n}: OrganizationProps) {\n  if (!view && !path) {\n    throw new Error(\"[Better Auth UI] Either `view` or `path` must be provided\")\n  }\n\n  const { authClient, basePaths, localization, navigate } = useAuth()\n  useAuthenticate(authClient)\n\n  const {\n    localization: organizationLocalization,\n    viewPaths: organizationViewPaths,\n    slug,\n    slugPrefix\n  } = useAuthPlugin(organizationPlugin)\n\n  const { data: activeOrganization, isPending } = useActiveOrganization(\n    authClient as OrganizationAuthClient\n  )\n\n  useEffect(() => {\n    if (!isPending && !activeOrganization) {\n      navigate({\n        to: `${basePaths.settings}/${organizationViewPaths.settings?.organizations}`,\n        replace: true\n      })\n    }\n  }, [\n    basePaths.settings,\n    isPending,\n    navigate,\n    organizationViewPaths.settings?.organizations,\n    activeOrganization\n  ])\n\n  const currentView = useMemo(() => {\n    if (view) return view\n\n    const match = Object.entries(organizationViewPaths.organization).find(\n      ([, segment]) => segment === path\n    )\n\n    return match?.[0] as OrganizationView | undefined\n  }, [view, path, organizationViewPaths.organization])\n\n  if (!currentView) {\n    const validPaths = Object.values(organizationViewPaths.organization).join(\n      \", \"\n    )\n    throw new Error(\n      `[Better Auth UI] Unknown organization path \"${path}\". Valid paths are: ${validPaths}`\n    )\n  }\n\n  if (!isPending && !activeOrganization) {\n    return null\n  }\n\n  return (\n    <Tabs\n      value={currentView}\n      className={cn(\"w-full gap-4 md:gap-6\", className)}\n    >\n      <div className={cn(hideNav && \"hidden\")}>\n        <TabsList aria-label={localization.settings.settings}>\n          <TabsTrigger\n            value=\"settings\"\n            className=\"gap-1\"\n            onClick={() =>\n              navigate({\n                to: slug\n                  ? `${basePaths.organization}/${slugPrefix}${slug}/${organizationViewPaths.organization.settings}`\n                  : `${basePaths.organization}/${organizationViewPaths.organization.settings}`\n              })\n            }\n          >\n            <SettingsIcon className=\"text-muted-foreground\" />\n\n            {localization.settings.settings}\n          </TabsTrigger>\n\n          <TabsTrigger\n            value=\"people\"\n            className=\"gap-1\"\n            onClick={() =>\n              navigate({\n                to: slug\n                  ? `${basePaths.organization}/${slugPrefix}${slug}/${organizationViewPaths.organization.people}`\n                  : `${basePaths.organization}/${organizationViewPaths.organization.people}`\n              })\n            }\n          >\n            <UserIcon className=\"text-muted-foreground\" />\n\n            {organizationLocalization.people}\n          </TabsTrigger>\n        </TabsList>\n      </div>\n\n      <TabsContent value=\"settings\" tabIndex={-1}>\n        <OrganizationSettings />\n      </TabsContent>\n\n      <TabsContent value=\"people\" tabIndex={-1}>\n        <OrganizationPeople />\n      </TabsContent>\n    </Tabs>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-switcher.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useActiveOrganization,\n  useAuth,\n  useAuthPlugin,\n  useListOrganizations,\n  useSession,\n  useSetActiveOrganization\n} from \"@better-auth-ui/react\"\nimport type { Organization } from \"better-auth/client\"\nimport {\n  ChevronsUpDown,\n  PlusCircle,\n  Settings as SettingsIcon\n} from \"lucide-react\"\nimport { type ComponentProps, type ReactElement, useState } from \"react\"\n\nimport { buttonVariants } from \"@/components/ui/button\"\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger\n} from \"@/components/ui/dropdown-menu\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { UserView } from \"../user/user-view\"\nimport { CreateOrganizationDialog } from \"./create-organization-dialog\"\nimport { OrganizationView } from \"./organization-view\"\n\n/** Props for the `OrganizationSwitcher` component. */\nexport type OrganizationSwitcherProps = {\n  className?: string\n  align?: \"center\" | \"end\" | \"start\"\n  side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n  sideOffset?: number\n  trigger?: ReactElement<ComponentProps<typeof DropdownMenuTrigger>>\n  hideCreate?: boolean\n  hidePersonal?: boolean\n  hideSettings?: boolean\n  hideSlug?: boolean\n  setActive?: (organization: Organization | null) => void\n}\n\n/**\n * Renders an organizations dropdown with a trigger button,\n * header summary, and a menu of organizations to switch to.\n */\nexport function OrganizationSwitcher({\n  className,\n  align,\n  side,\n  sideOffset,\n  hideCreate,\n  hidePersonal,\n  hideSettings,\n  hideSlug = true,\n  setActive,\n  trigger\n}: OrganizationSwitcherProps) {\n  const { authClient, navigate, basePaths, localization, viewPaths, Link } =\n    useAuth()\n  const { data: session, isPending: sessionPending } = useSession(authClient)\n  const {\n    localization: organizationLocalization,\n    viewPaths: organizationViewPaths,\n    slug,\n    slugPrefix\n  } = useAuthPlugin(organizationPlugin)\n\n  const { data: activeOrganization, isPending: activeOrganizationPending } =\n    useActiveOrganization(authClient as OrganizationAuthClient)\n\n  const { data: organizations, isPending: organizationsPending } =\n    useListOrganizations(authClient as OrganizationAuthClient)\n\n  const { mutate: setActiveOrganization } = useSetActiveOrganization(\n    authClient as OrganizationAuthClient\n  )\n\n  const isPending =\n    sessionPending ||\n    (!!session && (organizationsPending || activeOrganizationPending))\n\n  const [createOpen, setCreateOpen] = useState(false)\n  const [dropdownOpen, setDropdownOpen] = useState(false)\n\n  const otherOrganizations =\n    organizations?.filter(\n      (organization) => organization.id !== activeOrganization?.id\n    ) ?? []\n\n  const hasOtherEntries =\n    otherOrganizations.length > 0 || (!!activeOrganization && !hidePersonal)\n\n  function handleSetActive(organization: Organization | null) {\n    setDropdownOpen(false)\n\n    if (setActive) {\n      setActive(organization)\n    } else if (slug !== undefined) {\n      navigate({\n        to: organization\n          ? `${basePaths.organization}/${slugPrefix}${organization.slug}/${organizationViewPaths.organization.settings}`\n          : `${basePaths.settings}/${viewPaths.settings.account}`\n      })\n    } else {\n      setActiveOrganization({ organizationId: organization?.id ?? null })\n    }\n  }\n\n  return (\n    <>\n      <DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>\n        {trigger ?? (\n          <DropdownMenuTrigger\n            className={cn(\n              buttonVariants({ variant: \"ghost\" }),\n              \"h-auto px-2 py-2 text-left\",\n              className\n            )}\n            disabled={!session || isPending}\n          >\n            {isPending ? (\n              <OrganizationView isPending hideRole hideSlug={hideSlug} />\n            ) : activeOrganization ? (\n              <OrganizationView hideRole hideSlug={hideSlug} />\n            ) : session && !hidePersonal ? (\n              <UserView hideSubtitle={hideSlug} />\n            ) : (\n              <OrganizationView\n                hideRole\n                hideSlug={hideSlug}\n                organization={{ name: organizationLocalization.organization }}\n              />\n            )}\n\n            <ChevronsUpDown className=\"size-4 shrink-0 text-muted-foreground\" />\n          </DropdownMenuTrigger>\n        )}\n\n        <DropdownMenuContent\n          align={align}\n          side={side}\n          sideOffset={sideOffset}\n          className=\"min-w-64 max-w-svw\"\n        >\n          {activeOrganization ? (\n            <div className=\"flex items-center justify-between gap-4 px-2 py-2\">\n              <OrganizationView\n                hideRole\n                hideSlug={hideSlug}\n                organization={activeOrganization}\n              />\n\n              {!hideSettings && (\n                <Link\n                  href={\n                    slug\n                      ? `${basePaths.organization}/${slugPrefix}${slug}/${organizationViewPaths.organization.settings}`\n                      : `${basePaths.organization}/${organizationViewPaths.organization.settings}`\n                  }\n                  className={cn(\n                    buttonVariants({ variant: \"outline\", size: \"sm\" })\n                  )}\n                >\n                  <SettingsIcon className=\"text-muted-foreground\" />\n\n                  {organizationLocalization.manage}\n                </Link>\n              )}\n            </div>\n          ) : !isPending && session?.user && !hidePersonal ? (\n            <div className=\"flex items-center justify-between gap-4 px-2 py-2\">\n              <UserView hideSubtitle={hideSlug} />\n\n              {!hideSettings && (\n                <Link\n                  href={`${basePaths.settings}/${viewPaths.settings.account}`}\n                  className={cn(\n                    buttonVariants({ variant: \"outline\", size: \"sm\" })\n                  )}\n                >\n                  <SettingsIcon className=\"text-muted-foreground\" />\n\n                  {localization.settings.settings}\n                </Link>\n              )}\n            </div>\n          ) : null}\n\n          <DropdownMenuSeparator />\n\n          {!!activeOrganization && !hidePersonal && (\n            <DropdownMenuItem onClick={() => handleSetActive(null)}>\n              <UserView hideSubtitle={hideSlug} />\n            </DropdownMenuItem>\n          )}\n\n          {otherOrganizations.map((organization) => (\n            <DropdownMenuItem\n              key={organization.id}\n              onClick={() => handleSetActive(organization)}\n            >\n              <OrganizationView\n                hideRole\n                hideSlug={hideSlug}\n                organization={organization}\n              />\n            </DropdownMenuItem>\n          ))}\n\n          {!hideCreate && (\n            <>\n              {hasOtherEntries && <DropdownMenuSeparator />}\n\n              <DropdownMenuItem\n                onClick={() => {\n                  setDropdownOpen(false)\n                  setCreateOpen(true)\n                }}\n              >\n                <PlusCircle className=\"text-muted-foreground\" />\n\n                {organizationLocalization.createOrganization}\n              </DropdownMenuItem>\n            </>\n          )}\n        </DropdownMenuContent>\n      </DropdownMenu>\n\n      <CreateOrganizationDialog\n        open={createOpen}\n        onOpenChange={setCreateOpen}\n      />\n    </>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-switcher.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-settings.tsx",
      "content": "\"use client\"\n\nimport { useAuth } from \"@better-auth-ui/react\"\nimport type { ComponentProps } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { OrganizationDangerZone } from \"./organization-danger-zone\"\nimport { OrganizationProfile } from \"./organization-profile\"\n\nexport type OrganizationSettingsProps = {\n  className?: string\n}\n\n/**\n * Organization settings UI: profile card, plugin-contributed cards\n * (`organizationCards`), then danger zone.\n */\nexport function OrganizationSettings({\n  className,\n  ...props\n}: OrganizationSettingsProps & ComponentProps<\"div\">) {\n  const { plugins } = useAuth()\n\n  return (\n    <div className={cn(\"flex flex-col gap-4 md:gap-6\", className)} {...props}>\n      <OrganizationProfile />\n\n      {plugins.flatMap((plugin) =>\n        plugin.organizationCards?.map((Card, index) => (\n          <Card key={`${plugin.id}-${index.toString()}`} />\n        ))\n      )}\n\n      <OrganizationDangerZone />\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-settings.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-people.tsx",
      "content": "\"use client\"\n\nimport type { ComponentProps } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { OrganizationInvitations } from \"./organization-invitations\"\nimport { OrganizationMembers } from \"./organization-members\"\n\n/** Props for the `OrganizationPeople` component. */\nexport type OrganizationPeopleProps = {\n  className?: string\n}\n\n/**\n * Organization people UI: members table (see `OrganizationMembers`), then org\n * invitations.\n */\nexport function OrganizationPeople({\n  className,\n  ...props\n}: OrganizationPeopleProps & ComponentProps<\"div\">) {\n  return (\n    <div className={cn(\"flex flex-col gap-4 md:gap-6\", className)} {...props}>\n      <OrganizationMembers />\n      <OrganizationInvitations />\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-people.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-profile.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useActiveOrganization,\n  useAuth,\n  useAuthPlugin,\n  useUpdateOrganization\n} from \"@better-auth-ui/react\"\nimport { type SyntheticEvent, useEffect, useState } from \"react\"\nimport { toast } from \"sonner\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Field, FieldError, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { ChangeOrganizationLogo } from \"./change-organization-logo\"\nimport { SlugField } from \"./slug-field\"\n\nexport type OrganizationProfileProps = {\n  className?: string\n}\n\n/**\n * Profile card for the active organization: logo (when enabled), display name, and slug.\n */\nexport function OrganizationProfile({ className }: OrganizationProfileProps) {\n  const { authClient, localization } = useAuth()\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  const { data: activeOrganization } = useActiveOrganization(\n    authClient as OrganizationAuthClient\n  )\n\n  const [slug, setSlug] = useState(activeOrganization?.slug ?? \"\")\n\n  useEffect(() => {\n    setSlug(activeOrganization?.slug ?? \"\")\n  }, [activeOrganization?.slug])\n\n  const { mutate: commitOrganizationUpdate, isPending } = useUpdateOrganization(\n    authClient as OrganizationAuthClient,\n    {\n      onSuccess: () =>\n        toast.success(organizationLocalization.organizationUpdatedSuccess)\n    }\n  )\n\n  function handleSubmit(e: SyntheticEvent<HTMLFormElement>) {\n    e.preventDefault()\n    if (!activeOrganization) return\n\n    const formData = new FormData(e.currentTarget)\n    const name = formData.get(\"name\") as string\n\n    commitOrganizationUpdate({\n      data: { name, slug }\n    })\n  }\n\n  const nameInputId = `${activeOrganization?.id ?? \"org\"}-name`\n  const slugInputId = `${activeOrganization?.id ?? \"org\"}-slug`\n\n  return (\n    <div>\n      <h2 className={cn(\"mb-3 text-sm font-semibold\")}>\n        {organizationLocalization.organizationProfile}\n      </h2>\n\n      <Card className={className}>\n        <CardContent>\n          <form onSubmit={handleSubmit} className=\"flex flex-col gap-4\">\n            <ChangeOrganizationLogo />\n\n            <Field>\n              <FieldLabel htmlFor={nameInputId}>\n                {organizationLocalization.name}\n              </FieldLabel>\n\n              {activeOrganization ? (\n                <Input\n                  key={activeOrganization.id}\n                  id={nameInputId}\n                  name=\"name\"\n                  defaultValue={activeOrganization.name}\n                  autoComplete=\"organization\"\n                  placeholder={organizationLocalization.namePlaceholder}\n                  disabled={isPending}\n                />\n              ) : (\n                <Skeleton className=\"h-8 w-full rounded-md\" />\n              )}\n\n              <FieldError />\n            </Field>\n\n            {activeOrganization ? (\n              <SlugField\n                id={slugInputId}\n                value={slug}\n                onChange={setSlug}\n                currentSlug={activeOrganization.slug}\n                disabled={isPending}\n              />\n            ) : (\n              <Field>\n                <FieldLabel>{organizationLocalization.slug}</FieldLabel>\n                <Skeleton className=\"h-8 w-full rounded-md\" />\n              </Field>\n            )}\n\n            <Button\n              type=\"submit\"\n              disabled={isPending || !activeOrganization}\n              size=\"sm\"\n              className=\"mt-1 w-fit\"\n            >\n              {isPending && <Spinner />}\n\n              {localization.settings.saveChanges}\n            </Button>\n          </form>\n        </CardContent>\n      </Card>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-profile.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-danger-zone.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useHasPermission\n} from \"@better-auth-ui/react\"\nimport type { ComponentProps } from \"react\"\n\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { cn } from \"@/lib/utils\"\nimport { DeleteOrganization } from \"./delete-organization\"\nimport { DeleteOrganizationSkeleton } from \"./delete-organization-skeleton\"\nimport { LeaveOrganization } from \"./leave-organization\"\n\nexport type OrganizationDangerZoneProps = {\n  className?: string\n}\n\n/**\n * Danger zone heading with `LeaveOrganization` and `DeleteOrganization`\n * for the active organization in a single card.\n *\n * Resolves the `organization:delete` permission before rendering anything to\n * avoid flashing `LeaveOrganization` (and a stray separator) before the\n * delete row appears or disappears.\n */\nexport function OrganizationDangerZone({\n  className,\n  ...props\n}: OrganizationDangerZoneProps & ComponentProps<\"div\">) {\n  const { authClient, localization } = useAuth()\n\n  const { data: deletePermission, isPending: deletePermissionPending } =\n    useHasPermission(authClient as OrganizationAuthClient, {\n      permissions: { organization: [\"delete\"] }\n    })\n\n  const canDelete = !!deletePermission?.success\n\n  return (\n    <div className={cn(\"flex w-full flex-col\", className)} {...props}>\n      <h2 className=\"mb-3 text-sm font-semibold text-destructive\">\n        {localization.settings.dangerZone}\n      </h2>\n\n      <Card>\n        <CardContent>\n          {deletePermissionPending ? (\n            <DeleteOrganizationSkeleton />\n          ) : (\n            <>\n              <LeaveOrganization />\n\n              {canDelete && (\n                <>\n                  <Separator className=\"my-4\" />\n\n                  <DeleteOrganization />\n                </>\n              )}\n            </>\n          )}\n        </CardContent>\n      </Card>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-danger-zone.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-members.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useActiveOrganization,\n  useAuth,\n  useAuthPlugin,\n  useHasPermission,\n  useListOrganizationMembers,\n  useSession\n} from \"@better-auth-ui/react\"\nimport type { Member } from \"better-auth/client\"\nimport { ChevronUp, Filter, Search, X } from \"lucide-react\"\nimport { type ComponentProps, type ReactNode, useMemo, useState } from \"react\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport { Card } from \"@/components/ui/card\"\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuRadioGroup,\n  DropdownMenuRadioItem,\n  DropdownMenuTrigger\n} from \"@/components/ui/dropdown-menu\"\nimport {\n  InputGroup,\n  InputGroupAddon,\n  InputGroupInput\n} from \"@/components/ui/input-group\"\nimport {\n  Table,\n  TableBody,\n  TableHead,\n  TableHeader,\n  TableRow\n} from \"@/components/ui/table\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { InviteMemberDialog } from \"./invite-member-dialog\"\nimport { OrganizationMemberRow } from \"./organization-member-row\"\nimport { OrganizationMemberRowSkeleton } from \"./organization-member-row-skeleton\"\n\ntype SortDirection = \"ascending\" | \"descending\"\n\ntype SortDescriptor = {\n  column: string\n  direction: SortDirection\n}\n\n/** Props for the `OrganizationMembers` component. */\nexport type OrganizationMembersProps = {\n  className?: string\n}\n\n/**\n * Organization members table with title, invite control, and per-row actions.\n */\nexport function OrganizationMembers({\n  className,\n  ...props\n}: OrganizationMembersProps & ComponentProps<\"div\">) {\n  const { authClient } = useAuth()\n  const { localization: organizationLocalization, roles } =\n    useAuthPlugin(organizationPlugin)\n\n  const { data: session } = useSession(authClient)\n  const { data: activeOrganization, isPending: activeOrganizationPending } =\n    useActiveOrganization(authClient as OrganizationAuthClient)\n  const { data: membersData, isPending: membersPending } =\n    useListOrganizationMembers(authClient as OrganizationAuthClient)\n\n  const { isPending: updatePermissionPending } = useHasPermission(\n    authClient as OrganizationAuthClient,\n    {\n      permissions: { member: [\"update\"] }\n    }\n  )\n  const { isPending: deletePermissionPending } = useHasPermission(\n    authClient as OrganizationAuthClient,\n    {\n      permissions: { member: [\"delete\"] }\n    }\n  )\n\n  const isPending =\n    activeOrganizationPending ||\n    membersPending ||\n    updatePermissionPending ||\n    deletePermissionPending\n\n  const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>()\n  const [roleFilter, setRoleFilter] = useState(\"all\")\n  const [search, setSearch] = useState(\"\")\n\n  const filteredMembers = useMemo(() => {\n    return membersData?.members.filter(\n      (member) =>\n        (roleFilter === \"all\" || member.role === roleFilter) &&\n        (member.user.name.toLowerCase().includes(search.toLowerCase()) ||\n          member.user.email.toLowerCase().includes(search.toLowerCase()))\n    )\n  }, [search, membersData?.members, roleFilter])\n\n  const sortedMembers = useMemo(() => {\n    if (!sortDescriptor) return filteredMembers\n    if (!filteredMembers) return filteredMembers\n\n    return [...filteredMembers].sort((a, b) => {\n      const col = sortDescriptor.column as keyof Member | \"user\"\n      const first =\n        col === \"user\" ? a.user.name || a.user.email : String(a[col])\n      const second =\n        col === \"user\" ? b.user.name || b.user.email : String(b[col])\n\n      let cmp = first.localeCompare(second)\n      if (sortDescriptor.direction === \"descending\") {\n        cmp *= -1\n      }\n\n      return cmp\n    })\n  }, [sortDescriptor, filteredMembers])\n\n  const [inviteOpen, setInviteOpen] = useState(false)\n\n  const isOwner = membersData?.members.some(\n    (member) => member.role === \"owner\" && member.userId === session?.user.id\n  )\n\n  function toggleSort(column: string) {\n    setSortDescriptor((current) => {\n      if (current?.column !== column) {\n        return { column, direction: \"ascending\" }\n      }\n      if (current.direction === \"ascending\") {\n        return { column, direction: \"descending\" }\n      }\n      return undefined\n    })\n  }\n\n  return (\n    <div className={cn(\"flex flex-col gap-3\", className)} {...props}>\n      <div className=\"flex items-end justify-between gap-3\">\n        <h3 className=\"truncate text-sm font-semibold\">\n          {organizationLocalization.members}\n        </h3>\n\n        <Button\n          className=\"shrink-0\"\n          size=\"sm\"\n          disabled={isPending}\n          onClick={() => setInviteOpen(true)}\n        >\n          {organizationLocalization.inviteMember}\n        </Button>\n      </div>\n\n      <div className=\"flex flex-col gap-4\">\n        <div className=\"flex items-center gap-3\">\n          <InputGroup className=\"min-w-0 sm:w-[220px]\">\n            <InputGroupInput\n              type=\"search\"\n              value={search}\n              onChange={(e) => setSearch(e.target.value)}\n              aria-label={organizationLocalization.search}\n              placeholder={organizationLocalization.search}\n              disabled={isPending}\n            />\n\n            <InputGroupAddon>\n              <Search className=\"text-muted-foreground\" />\n            </InputGroupAddon>\n          </InputGroup>\n\n          <DropdownMenu>\n            <DropdownMenuTrigger\n              className={cn(buttonVariants({ size: \"sm\", variant: \"outline\" }))}\n              disabled={isPending}\n            >\n              <Filter />\n\n              {organizationLocalization.role}\n            </DropdownMenuTrigger>\n\n            <DropdownMenuContent align=\"start\">\n              <DropdownMenuRadioGroup\n                value={roleFilter}\n                onValueChange={setRoleFilter}\n              >\n                <DropdownMenuRadioItem value=\"all\">\n                  {organizationLocalization.all}\n                </DropdownMenuRadioItem>\n\n                {Object.entries(roles).map(([role, label]) => (\n                  <DropdownMenuRadioItem key={role} value={role}>\n                    {label}\n                  </DropdownMenuRadioItem>\n                ))}\n              </DropdownMenuRadioGroup>\n            </DropdownMenuContent>\n          </DropdownMenu>\n        </div>\n\n        {roleFilter !== \"all\" && (\n          <Badge variant=\"secondary\" className=\"w-fit gap-1\">\n            {organizationLocalization.role}:{\" \"}\n            <span className=\"capitalize\">\n              {roles?.[roleFilter] ?? roleFilter}\n            </span>\n            <Button\n              aria-label={organizationLocalization.clear}\n              className=\"size-4 rounded-sm text-muted-foreground\"\n              onClick={() => setRoleFilter(\"all\")}\n              size=\"icon-xs\"\n              type=\"button\"\n              variant=\"ghost\"\n            >\n              <X className=\"size-3\" />\n            </Button>\n          </Badge>\n        )}\n\n        <Card className=\"p-0\">\n          <Table aria-label={organizationLocalization.members}>\n            <TableHeader>\n              <TableRow>\n                <SortableTableHead\n                  sortDirection={\n                    sortDescriptor?.column === \"user\"\n                      ? sortDescriptor.direction\n                      : undefined\n                  }\n                  onClick={() => toggleSort(\"user\")}\n                >\n                  {organizationLocalization.member}\n                </SortableTableHead>\n\n                <SortableTableHead\n                  sortDirection={\n                    sortDescriptor?.column === \"role\"\n                      ? sortDescriptor.direction\n                      : undefined\n                  }\n                  onClick={() => toggleSort(\"role\")}\n                >\n                  {organizationLocalization.role}\n                </SortableTableHead>\n\n                <TableHead className=\"text-end\">\n                  {organizationLocalization.actions}\n                </TableHead>\n              </TableRow>\n            </TableHeader>\n\n            <TableBody>\n              {isPending ? (\n                <OrganizationMemberRowSkeleton />\n              ) : (\n                !!activeOrganization &&\n                sortedMembers?.map((member) => (\n                  <OrganizationMemberRow\n                    key={member.id}\n                    member={member}\n                    isOwner={isOwner}\n                    organization={activeOrganization}\n                  />\n                ))\n              )}\n            </TableBody>\n          </Table>\n        </Card>\n      </div>\n\n      <InviteMemberDialog open={inviteOpen} onOpenChange={setInviteOpen} />\n    </div>\n  )\n}\n\nfunction SortableTableHead({\n  children,\n  sortDirection,\n  onClick\n}: {\n  children: ReactNode\n  sortDirection?: SortDirection\n  onClick: () => void\n}) {\n  return (\n    <TableHead aria-sort={sortDirection ?? \"none\"}>\n      <Button\n        className=\"h-auto w-full justify-start p-0 font-medium hover:bg-transparent\"\n        onClick={onClick}\n        size=\"sm\"\n        type=\"button\"\n        variant=\"ghost\"\n      >\n        {children}\n\n        {!!sortDirection && (\n          <ChevronUp\n            className={cn(\n              \"size-3 transition-transform duration-100 ease-out\",\n              sortDirection === \"descending\" ? \"rotate-180\" : \"\"\n            )}\n          />\n        )}\n      </Button>\n    </TableHead>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-members.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-member-row.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useHasPermission,\n  useSession,\n  useUpdateMemberRole\n} from \"@better-auth-ui/react\"\nimport type { Member, Organization, User } from \"better-auth/client\"\nimport { LogOut, Pencil, Trash2 } from \"lucide-react\"\nimport { useState } from \"react\"\nimport { toast } from \"sonner\"\n\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger\n} from \"@/components/ui/dropdown-menu\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { TableCell, TableRow } from \"@/components/ui/table\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { UserView } from \"../user/user-view\"\nimport { LeaveOrganizationDialog } from \"./leave-organization-dialog\"\nimport { OrganizationMemberRowSkeleton } from \"./organization-member-row-skeleton\"\nimport { RemoveMemberDialog } from \"./remove-member-dialog\"\n\nexport type OrganizationMemberRowProps = {\n  member: Member & { user: Partial<User> }\n  isOwner?: boolean\n  organization: Organization\n}\n\nexport function OrganizationMemberRow({\n  member,\n  isOwner,\n  organization\n}: OrganizationMemberRowProps) {\n  const { authClient } = useAuth()\n  const { localization: organizationLocalization, roles } =\n    useAuthPlugin(organizationPlugin)\n\n  const { data: session } = useSession(authClient)\n\n  const { data: hasUpdatePermission, isPending: updatePermissionPending } =\n    useHasPermission(authClient as OrganizationAuthClient, {\n      permissions: { member: [\"update\"] }\n    })\n\n  const { data: hasDeletePermission, isPending: deletePermissionPending } =\n    useHasPermission(authClient as OrganizationAuthClient, {\n      permissions: { member: [\"delete\"] }\n    })\n\n  const isPending = updatePermissionPending || deletePermissionPending\n\n  const { mutate: updateMemberRole, isPending: isUpdatingRole } =\n    useUpdateMemberRole(authClient as OrganizationAuthClient, {\n      onSuccess: () => toast.success(organizationLocalization.memberRoleUpdated)\n    })\n\n  const roleLabel = roles?.[member.role] ?? member.role\n\n  const assignableRoles = Object.entries(roles).filter(\n    ([key]) => isOwner || key !== \"owner\"\n  )\n\n  const isCurrentUser = session?.user.id === member.userId\n\n  const [removeOpen, setRemoveOpen] = useState(false)\n  const [leaveOpen, setLeaveOpen] = useState(false)\n\n  if (isPending) {\n    return <OrganizationMemberRowSkeleton />\n  }\n\n  return (\n    <TableRow>\n      <TableCell>\n        <UserView user={member.user} />\n      </TableCell>\n\n      <TableCell>{roleLabel}</TableCell>\n\n      <TableCell>\n        <div className=\"flex items-center justify-end gap-1\">\n          {hasUpdatePermission?.success && (\n            <DropdownMenu>\n              <DropdownMenuTrigger\n                className={cn(\n                  buttonVariants({ size: \"icon\", variant: \"ghost\" }),\n                  \"size-8\"\n                )}\n                disabled={isUpdatingRole}\n                aria-label={organizationLocalization.changeMemberRole}\n              >\n                {isUpdatingRole ? <Spinner /> : <Pencil />}\n              </DropdownMenuTrigger>\n\n              <DropdownMenuContent align=\"end\">\n                {assignableRoles.map(([role, label]) => (\n                  <DropdownMenuItem\n                    key={role}\n                    disabled={member.role === role}\n                    onClick={() =>\n                      updateMemberRole({ memberId: member.id, role })\n                    }\n                  >\n                    {label}\n                  </DropdownMenuItem>\n                ))}\n              </DropdownMenuContent>\n            </DropdownMenu>\n          )}\n\n          {isCurrentUser ? (\n            <Button\n              size=\"icon\"\n              variant=\"outline\"\n              className=\"size-8 text-destructive\"\n              aria-label={organizationLocalization.leaveOrganization}\n              onClick={() => setLeaveOpen(true)}\n            >\n              <LogOut />\n            </Button>\n          ) : (\n            hasDeletePermission?.success && (\n              <Button\n                size=\"icon\"\n                variant=\"outline\"\n                className=\"size-8 text-destructive\"\n                aria-label={organizationLocalization.removeMember}\n                onClick={() => setRemoveOpen(true)}\n              >\n                <Trash2 />\n              </Button>\n            )\n          )}\n        </div>\n\n        {isCurrentUser && organization ? (\n          <LeaveOrganizationDialog\n            open={leaveOpen}\n            onOpenChange={setLeaveOpen}\n            organization={organization}\n          />\n        ) : (\n          hasDeletePermission?.success && (\n            <RemoveMemberDialog\n              open={removeOpen}\n              onOpenChange={setRemoveOpen}\n              member={member}\n            />\n          )\n        )}\n      </TableCell>\n    </TableRow>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-member-row.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-member-row-skeleton.tsx",
      "content": "\"use client\"\n\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport { TableCell, TableRow } from \"@/components/ui/table\"\nimport { UserView } from \"../user/user-view\"\n\n/**\n * Placeholder row matching `OrganizationMemberRow` while members load.\n */\nexport function OrganizationMemberRowSkeleton() {\n  return (\n    <TableRow>\n      <TableCell>\n        <UserView isPending />\n      </TableCell>\n\n      <TableCell>\n        <Skeleton className=\"h-4 w-18 rounded-md\" />\n      </TableCell>\n\n      <TableCell className=\"flex justify-end\">\n        <Skeleton className=\"size-8 rounded-md\" />\n      </TableCell>\n    </TableRow>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-member-row-skeleton.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-invitations.tsx",
      "content": "\"use client\"\n\nimport type { OrganizationLocalization } from \"@better-auth-ui/core/plugins\"\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useHasPermission,\n  useListOrganizationInvitations\n} from \"@better-auth-ui/react\"\nimport { ChevronUp, Filter, Search, X } from \"lucide-react\"\nimport { type ComponentProps, type ReactNode, useMemo, useState } from \"react\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport { Card } from \"@/components/ui/card\"\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuRadioGroup,\n  DropdownMenuRadioItem,\n  DropdownMenuTrigger\n} from \"@/components/ui/dropdown-menu\"\nimport {\n  InputGroup,\n  InputGroupAddon,\n  InputGroupInput\n} from \"@/components/ui/input-group\"\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow\n} from \"@/components/ui/table\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { InviteMemberDialog } from \"./invite-member-dialog\"\nimport { OrganizationInvitationRow } from \"./organization-invitation-row\"\nimport { OrganizationInvitationRowSkeleton } from \"./organization-invitation-row-skeleton\"\nimport { OrganizationInvitationsEmpty } from \"./organization-invitations-empty\"\n\ntype SortDirection = \"ascending\" | \"descending\"\n\ntype SortDescriptor = {\n  column: string\n  direction: SortDirection\n}\n\n/** Props for the `OrganizationInvitations` component. */\nexport type OrganizationInvitationsProps = {\n  className?: string\n}\n\n/**\n * Organization invitations table with invite control and per-row actions.\n */\nexport function OrganizationInvitations({\n  className,\n  ...props\n}: OrganizationInvitationsProps & ComponentProps<\"div\">) {\n  const { authClient, localization } = useAuth()\n  const { localization: organizationLocalization, roles } =\n    useAuthPlugin(organizationPlugin)\n\n  const { data: invitations, isPending: invitationsPending } =\n    useListOrganizationInvitations(authClient as OrganizationAuthClient)\n\n  const { isPending: invitationPermissionPending } = useHasPermission(\n    authClient as OrganizationAuthClient,\n    {\n      permissions: { invitation: [\"cancel\"] }\n    }\n  )\n\n  const isPending = invitationsPending || invitationPermissionPending\n\n  const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>()\n  const [roleFilter, setRoleFilter] = useState(\"all\")\n  const [statusFilter, setStatusFilter] = useState(\"all\")\n  const [search, setSearch] = useState(\"\")\n\n  const filteredInvitations = useMemo(() => {\n    return invitations?.filter(\n      (invitation) =>\n        (roleFilter === \"all\" || invitation.role === roleFilter) &&\n        (statusFilter === \"all\" || invitation.status === statusFilter) &&\n        invitation.email.toLowerCase().includes(search.toLowerCase())\n    )\n  }, [search, invitations, roleFilter, statusFilter])\n\n  const sortedInvitations = useMemo(() => {\n    if (!sortDescriptor) return filteredInvitations\n    if (!filteredInvitations) return filteredInvitations\n\n    return [...filteredInvitations].sort((a, b) => {\n      const col = sortDescriptor.column as keyof typeof a\n      let cmp = 0\n\n      if (col === \"createdAt\") {\n        cmp = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()\n      } else {\n        cmp = String(a[col]).localeCompare(String(b[col]))\n      }\n\n      if (sortDescriptor.direction === \"descending\") {\n        cmp *= -1\n      }\n\n      return cmp\n    })\n  }, [sortDescriptor, filteredInvitations])\n\n  const [inviteOpen, setInviteOpen] = useState(false)\n\n  function toggleSort(column: string) {\n    setSortDescriptor((current) => {\n      if (current?.column !== column) {\n        return { column, direction: \"ascending\" }\n      }\n      if (current.direction === \"ascending\") {\n        return { column, direction: \"descending\" }\n      }\n      return undefined\n    })\n  }\n\n  return (\n    <div className={cn(\"flex flex-col gap-3\", className)} {...props}>\n      <h3 className=\"truncate text-sm font-semibold\">\n        {organizationLocalization.invitations}\n      </h3>\n\n      <div className=\"flex flex-col gap-4\">\n        <div className=\"flex items-center gap-3\">\n          <InputGroup className=\"min-w-0 sm:w-[220px]\">\n            <InputGroupInput\n              type=\"search\"\n              value={search}\n              onChange={(e) => setSearch(e.target.value)}\n              aria-label={organizationLocalization.search}\n              placeholder={organizationLocalization.search}\n              disabled={isPending}\n            />\n\n            <InputGroupAddon>\n              <Search className=\"text-muted-foreground\" />\n            </InputGroupAddon>\n          </InputGroup>\n\n          <DropdownMenu>\n            <DropdownMenuTrigger\n              className={cn(buttonVariants({ size: \"sm\", variant: \"outline\" }))}\n              disabled={isPending}\n            >\n              <Filter />\n\n              {organizationLocalization.role}\n            </DropdownMenuTrigger>\n\n            <DropdownMenuContent align=\"start\">\n              <DropdownMenuRadioGroup\n                value={roleFilter}\n                onValueChange={setRoleFilter}\n              >\n                <DropdownMenuRadioItem value=\"all\">\n                  {organizationLocalization.all}\n                </DropdownMenuRadioItem>\n\n                {Object.entries(roles).map(([key, label]) => (\n                  <DropdownMenuRadioItem key={key} value={key}>\n                    {label}\n                  </DropdownMenuRadioItem>\n                ))}\n              </DropdownMenuRadioGroup>\n            </DropdownMenuContent>\n          </DropdownMenu>\n\n          <DropdownMenu>\n            <DropdownMenuTrigger\n              className={cn(buttonVariants({ size: \"sm\", variant: \"outline\" }))}\n              disabled={isPending}\n            >\n              <Filter />\n\n              {organizationLocalization.status}\n            </DropdownMenuTrigger>\n\n            <DropdownMenuContent align=\"start\">\n              <DropdownMenuRadioGroup\n                value={statusFilter}\n                onValueChange={setStatusFilter}\n              >\n                <DropdownMenuRadioItem value=\"all\">\n                  {organizationLocalization.all}\n                </DropdownMenuRadioItem>\n\n                {([\"pending\", \"accepted\", \"rejected\", \"canceled\"] as const).map(\n                  (status) => (\n                    <DropdownMenuRadioItem key={status} value={status}>\n                      {organizationLocalization[\n                        status as keyof OrganizationLocalization\n                      ] ?? status}\n                    </DropdownMenuRadioItem>\n                  )\n                )}\n              </DropdownMenuRadioGroup>\n            </DropdownMenuContent>\n          </DropdownMenu>\n        </div>\n\n        {(roleFilter !== \"all\" || statusFilter !== \"all\") && (\n          <div className=\"flex flex-wrap gap-2\">\n            {roleFilter !== \"all\" && (\n              <Badge variant=\"secondary\" className=\"gap-1\">\n                {organizationLocalization.role}:{\" \"}\n                <span className=\"capitalize\">\n                  {roles?.[roleFilter] ?? roleFilter}\n                </span>\n                <Button\n                  aria-label={organizationLocalization.clear}\n                  className=\"size-4 rounded-sm text-muted-foreground\"\n                  onClick={() => setRoleFilter(\"all\")}\n                  size=\"icon-xs\"\n                  type=\"button\"\n                  variant=\"ghost\"\n                >\n                  <X className=\"size-3\" />\n                </Button>\n              </Badge>\n            )}\n\n            {statusFilter !== \"all\" && (\n              <Badge variant=\"secondary\" className=\"gap-1\">\n                {organizationLocalization.status}:{\" \"}\n                {organizationLocalization[\n                  statusFilter as keyof OrganizationLocalization\n                ] ?? statusFilter}\n                <Button\n                  aria-label={organizationLocalization.clear}\n                  className=\"size-4 rounded-sm text-muted-foreground\"\n                  onClick={() => setStatusFilter(\"all\")}\n                  size=\"icon-xs\"\n                  type=\"button\"\n                  variant=\"ghost\"\n                >\n                  <X className=\"size-3\" />\n                </Button>\n              </Badge>\n            )}\n          </div>\n        )}\n\n        <Card className=\"p-0\">\n          <Table aria-label={organizationLocalization.invitations}>\n            <TableHeader>\n              <TableRow>\n                <SortableTableHead\n                  sortDirection={\n                    sortDescriptor?.column === \"email\"\n                      ? sortDescriptor.direction\n                      : undefined\n                  }\n                  onClick={() => toggleSort(\"email\")}\n                >\n                  {localization.auth.email}\n                </SortableTableHead>\n\n                <SortableTableHead\n                  sortDirection={\n                    sortDescriptor?.column === \"createdAt\"\n                      ? sortDescriptor.direction\n                      : undefined\n                  }\n                  onClick={() => toggleSort(\"createdAt\")}\n                >\n                  {organizationLocalization.invitedAt}\n                </SortableTableHead>\n\n                <SortableTableHead\n                  sortDirection={\n                    sortDescriptor?.column === \"role\"\n                      ? sortDescriptor.direction\n                      : undefined\n                  }\n                  onClick={() => toggleSort(\"role\")}\n                >\n                  {organizationLocalization.role}\n                </SortableTableHead>\n\n                <SortableTableHead\n                  sortDirection={\n                    sortDescriptor?.column === \"status\"\n                      ? sortDescriptor.direction\n                      : undefined\n                  }\n                  onClick={() => toggleSort(\"status\")}\n                >\n                  {organizationLocalization.status}\n                </SortableTableHead>\n\n                <TableHead className=\"text-end\">\n                  {organizationLocalization.actions}\n                </TableHead>\n              </TableRow>\n            </TableHeader>\n\n            <TableBody>\n              {isPending ? (\n                <OrganizationInvitationRowSkeleton />\n              ) : !sortedInvitations?.length ? (\n                <TableRow>\n                  <TableCell colSpan={5}>\n                    <OrganizationInvitationsEmpty\n                      onInvitePress={() => setInviteOpen(true)}\n                    />\n                  </TableCell>\n                </TableRow>\n              ) : (\n                sortedInvitations.map((invitation) => (\n                  <OrganizationInvitationRow\n                    key={invitation.id}\n                    invitation={invitation}\n                  />\n                ))\n              )}\n            </TableBody>\n          </Table>\n        </Card>\n      </div>\n\n      <InviteMemberDialog open={inviteOpen} onOpenChange={setInviteOpen} />\n    </div>\n  )\n}\n\nfunction SortableTableHead({\n  children,\n  sortDirection,\n  onClick\n}: {\n  children: ReactNode\n  sortDirection?: SortDirection\n  onClick: () => void\n}) {\n  return (\n    <TableHead aria-sort={sortDirection ?? \"none\"}>\n      <Button\n        className=\"h-auto w-full justify-start p-0 font-medium hover:bg-transparent\"\n        onClick={onClick}\n        size=\"sm\"\n        type=\"button\"\n        variant=\"ghost\"\n      >\n        {children}\n\n        {!!sortDirection && (\n          <ChevronUp\n            className={cn(\n              \"size-3 transition-transform duration-100 ease-out\",\n              sortDirection === \"descending\" ? \"rotate-180\" : \"\"\n            )}\n          />\n        )}\n      </Button>\n    </TableHead>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-invitations.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-invitation-row.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useCancelInvitation,\n  useHasPermission\n} from \"@better-auth-ui/react\"\nimport type { Invitation } from \"better-auth/client\"\nimport { X } from \"lucide-react\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { TableCell, TableRow } from \"@/components/ui/table\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { OrganizationInvitationRowSkeleton } from \"./organization-invitation-row-skeleton\"\n\nexport type OrganizationInvitationRowProps = {\n  invitation: Invitation\n}\n\nconst statusBadgeClasses: Record<string, string> = {\n  pending: \"bg-amber-500/10 text-amber-600 dark:text-amber-400\",\n  accepted: \"bg-emerald-500/10 text-emerald-600 dark:text-emerald-400\",\n  rejected: \"bg-destructive/10 text-destructive\",\n  canceled: \"bg-muted text-muted-foreground\"\n}\n\nexport function OrganizationInvitationRow({\n  invitation\n}: OrganizationInvitationRowProps) {\n  const { authClient } = useAuth()\n  const { localization: organizationLocalization, roles } =\n    useAuthPlugin(organizationPlugin)\n\n  const {\n    data: cancelInvitationPermission,\n    isPending: cancelPermissionPending\n  } = useHasPermission(authClient as OrganizationAuthClient, {\n    permissions: { invitation: [\"cancel\"] }\n  })\n\n  const { mutate: cancelInvitation, isPending: cancelPending } =\n    useCancelInvitation(authClient as OrganizationAuthClient)\n\n  const roleLabel = roles?.[invitation.role] ?? invitation.role\n\n  const statusLabel =\n    organizationLocalization[\n      invitation.status as keyof typeof organizationLocalization\n    ] ?? invitation.status\n\n  if (cancelPermissionPending) {\n    return <OrganizationInvitationRowSkeleton />\n  }\n\n  return (\n    <TableRow>\n      <TableCell className=\"font-medium text-sm\">{invitation.email}</TableCell>\n\n      <TableCell className=\"text-muted-foreground text-xs tabular-nums whitespace-nowrap\">\n        {new Date(invitation.createdAt).toLocaleString(undefined, {\n          dateStyle: \"short\",\n          timeStyle: \"short\"\n        })}\n      </TableCell>\n\n      <TableCell className=\"text-sm\">{roleLabel}</TableCell>\n\n      <TableCell className=\"text-sm\">\n        <Badge\n          variant=\"secondary\"\n          className={cn(statusBadgeClasses[invitation.status])}\n        >\n          {String(statusLabel)}\n        </Badge>\n      </TableCell>\n\n      <TableCell className=\"text-end\">\n        {cancelInvitationPermission?.success &&\n          invitation.status === \"pending\" && (\n            <Button\n              size=\"icon\"\n              variant=\"outline\"\n              className=\"size-8 text-destructive\"\n              disabled={cancelPending}\n              onClick={() => cancelInvitation({ invitationId: invitation.id })}\n              aria-label={organizationLocalization.cancelInvitation}\n            >\n              {cancelPending ? <Spinner /> : <X />}\n            </Button>\n          )}\n      </TableCell>\n    </TableRow>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-invitation-row.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-invitation-row-skeleton.tsx",
      "content": "\"use client\"\n\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport { TableCell, TableRow } from \"@/components/ui/table\"\n\n/**\n * Placeholder row matching `OrganizationInvitationRow` while invitations load.\n */\nexport function OrganizationInvitationRowSkeleton() {\n  return (\n    <TableRow>\n      <TableCell>\n        <Skeleton className=\"h-4 w-48 rounded-md\" />\n      </TableCell>\n\n      <TableCell>\n        <Skeleton className=\"h-4 w-36 rounded-md\" />\n      </TableCell>\n\n      <TableCell>\n        <Skeleton className=\"h-4 w-16 rounded-md\" />\n      </TableCell>\n\n      <TableCell>\n        <Skeleton className=\"h-4 w-14 rounded-full\" />\n      </TableCell>\n\n      <TableCell />\n    </TableRow>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-invitation-row-skeleton.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-invitations-empty.tsx",
      "content": "\"use client\"\n\nimport { useAuthPlugin } from \"@better-auth-ui/react\"\nimport { Send } from \"lucide-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Empty,\n  EmptyContent,\n  EmptyDescription,\n  EmptyHeader,\n  EmptyMedia,\n  EmptyTitle\n} from \"@/components/ui/empty\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\n\nexport type OrganizationInvitationsEmptyProps = {\n  onInvitePress: () => void\n}\n\n/**\n * Empty state for `OrganizationInvitations`.\n */\nexport function OrganizationInvitationsEmpty({\n  onInvitePress\n}: OrganizationInvitationsEmptyProps) {\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  return (\n    <Empty>\n      <EmptyHeader>\n        <EmptyMedia variant=\"icon\">\n          <Send />\n        </EmptyMedia>\n        <EmptyTitle>{organizationLocalization.noInvitations}</EmptyTitle>\n        <EmptyDescription>\n          {organizationLocalization.organizationInvitationsEmptyDescription}\n        </EmptyDescription>\n      </EmptyHeader>\n      <EmptyContent>\n        <Button size=\"sm\" onClick={onInvitePress}>\n          {organizationLocalization.inviteMember}\n        </Button>\n      </EmptyContent>\n    </Empty>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-invitations-empty.tsx"
    },
    {
      "path": "src/components/auth/organization/organizations.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useListOrganizations\n} from \"@better-auth-ui/react\"\nimport { Fragment, useState } from \"react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Item, ItemGroup, ItemSeparator } from \"@/components/ui/item\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { CreateOrganizationDialog } from \"./create-organization-dialog\"\nimport { OrganizationRow } from \"./organization-row\"\nimport { OrganizationViewSkeleton } from \"./organization-view-skeleton\"\nimport { OrganizationsEmpty } from \"./organizations-empty\"\n\nexport type OrganizationsProps = {\n  className?: string\n}\n\n/**\n * Lists organizations the user belongs to (via `useListOrganizations`): loading skeleton,\n * empty state with create, or a card of rows with a Manage control per organization.\n * Owns `CreateOrganizationDialog` open state and the create actions.\n */\nexport function Organizations({ className }: OrganizationsProps) {\n  const { authClient } = useAuth()\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  const [createOpen, setCreateOpen] = useState(false)\n\n  const { data: organizations, isPending: organizationsPending } =\n    useListOrganizations(authClient as OrganizationAuthClient)\n\n  return (\n    <>\n      <div className={className}>\n        <div className=\"flex flex-col gap-3\">\n          <div className=\"flex items-end justify-between gap-3\">\n            <h2 className=\"truncate text-sm font-semibold\">\n              {organizationLocalization.organizations}\n            </h2>\n\n            <Button\n              className=\"shrink-0\"\n              size=\"sm\"\n              disabled={organizationsPending}\n              onClick={() => setCreateOpen(true)}\n            >\n              {organizationLocalization.createOrganization}\n            </Button>\n          </div>\n\n          <Card className=\"p-0\">\n            <CardContent className=\"p-0\">\n              {organizationsPending ? (\n                <ItemGroup>\n                  <Item>\n                    <OrganizationViewSkeleton />\n                  </Item>\n                </ItemGroup>\n              ) : !organizations?.length ? (\n                <OrganizationsEmpty onCreatePress={() => setCreateOpen(true)} />\n              ) : (\n                <ItemGroup className=\"gap-0\">\n                  {organizations.map((organization, index) => (\n                    <Fragment key={organization.id}>\n                      {index > 0 && <ItemSeparator />}\n                      <OrganizationRow organization={organization} />\n                    </Fragment>\n                  ))}\n                </ItemGroup>\n              )}\n            </CardContent>\n          </Card>\n        </div>\n      </div>\n\n      <CreateOrganizationDialog\n        open={createOpen}\n        onOpenChange={setCreateOpen}\n      />\n    </>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organizations.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-row.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useSetActiveOrganization\n} from \"@better-auth-ui/react\"\nimport type { Organization } from \"better-auth/client\"\nimport { Settings as SettingsIcon } from \"lucide-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Item, ItemActions } from \"@/components/ui/item\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { OrganizationView } from \"./organization-view\"\n\nexport type OrganizationRowProps = {\n  organization: Organization\n}\n\n/**\n * Single organization row: logo and labels via `OrganizationView`, plus a Manage action.\n */\nexport function OrganizationRow({ organization }: OrganizationRowProps) {\n  const { authClient, basePaths, navigate } = useAuth()\n  const {\n    localization: organizationLocalization,\n    viewPaths: organizationViewPaths,\n    slug,\n    slugPrefix\n  } = useAuthPlugin(organizationPlugin)\n\n  const { mutate: setActiveOrganization, isPending: setActivePending } =\n    useSetActiveOrganization(authClient as OrganizationAuthClient, {\n      onSuccess: () => {\n        navigate({\n          to: `${basePaths.organization}/${organizationViewPaths.organization.settings}`\n        })\n      }\n    })\n\n  function manageOrganization() {\n    if (slug !== undefined) {\n      navigate({\n        to: `${basePaths.organization}/${slugPrefix}${organization.slug}/${organizationViewPaths.organization.settings}`\n      })\n    } else {\n      setActiveOrganization({ organizationId: organization.id })\n    }\n  }\n\n  return (\n    <Item>\n      <OrganizationView organization={organization} />\n      <ItemActions>\n        <Button\n          variant=\"outline\"\n          size=\"sm\"\n          disabled={setActivePending}\n          onClick={manageOrganization}\n          aria-label={organizationLocalization.manage}\n        >\n          {setActivePending ? <Spinner /> : <SettingsIcon />}\n\n          {organizationLocalization.manage}\n        </Button>\n      </ItemActions>\n    </Item>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-row.tsx"
    },
    {
      "path": "src/components/auth/organization/organizations-settings.tsx",
      "content": "\"use client\"\n\nimport type { ComponentProps } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Organizations } from \"./organizations\"\nimport { UserInvitations } from \"./user-invitations\"\n\nexport type OrganizationsSettingsProps = {\n  className?: string\n}\n\n/**\n * Renders the organizations settings panel.\n *\n * Displays all organizations the user belongs to with an empty state and\n * create button, followed by a card for invitations to the user.\n */\nexport function OrganizationsSettings({\n  className,\n  ...props\n}: OrganizationsSettingsProps & ComponentProps<\"div\">) {\n  return (\n    <div\n      className={cn(\"flex w-full flex-col gap-4 md:gap-6\", className)}\n      {...props}\n    >\n      <Organizations />\n      <UserInvitations />\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organizations-settings.tsx"
    },
    {
      "path": "src/components/auth/organization/organizations-empty.tsx",
      "content": "\"use client\"\n\nimport { useAuthPlugin } from \"@better-auth-ui/react\"\nimport { Briefcase } from \"lucide-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Empty,\n  EmptyContent,\n  EmptyDescription,\n  EmptyHeader,\n  EmptyMedia,\n  EmptyTitle\n} from \"@/components/ui/empty\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\n\nexport type OrganizationsEmptyProps = {\n  onCreatePress: () => void\n}\n\nexport function OrganizationsEmpty({ onCreatePress }: OrganizationsEmptyProps) {\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  return (\n    <Empty>\n      <EmptyHeader>\n        <EmptyMedia variant=\"icon\">\n          <Briefcase />\n        </EmptyMedia>\n        <EmptyTitle>{organizationLocalization.noOrganizations}</EmptyTitle>\n        <EmptyDescription>\n          {organizationLocalization.organizationsDescription}\n        </EmptyDescription>\n      </EmptyHeader>\n      <EmptyContent>\n        <Button size=\"sm\" onClick={onCreatePress}>\n          {organizationLocalization.createOrganization}\n        </Button>\n      </EmptyContent>\n    </Empty>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organizations-empty.tsx"
    },
    {
      "path": "src/components/auth/organization/user-invitations.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useListUserInvitations\n} from \"@better-auth-ui/react\"\nimport { Fragment } from \"react\"\n\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { ItemGroup, ItemSeparator } from \"@/components/ui/item\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { UserInvitationRow } from \"./user-invitation-row\"\nimport { UserInvitationRowSkeleton } from \"./user-invitation-row-skeleton\"\nimport { UserInvitationsEmpty } from \"./user-invitations-empty\"\n\nexport type UserInvitationsProps = {\n  className?: string\n}\n\n/**\n * Organization invitations for the signed-in user. Always renders the section\n * card; uses `UserInvitationsEmpty` when there are no pending invitations.\n */\nexport function UserInvitations({ className }: UserInvitationsProps) {\n  const { authClient } = useAuth()\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  const { data: invitations, isPending } = useListUserInvitations(\n    authClient as OrganizationAuthClient\n  )\n\n  return (\n    <div className={className}>\n      <div className=\"flex flex-col gap-3\">\n        <h2 className=\"truncate text-sm font-semibold\">\n          {organizationLocalization.invitations}\n        </h2>\n\n        <Card className=\"p-0\">\n          <CardContent className=\"p-0\">\n            {isPending ? (\n              <ItemGroup>\n                <UserInvitationRowSkeleton />\n              </ItemGroup>\n            ) : !invitations?.length ? (\n              <UserInvitationsEmpty />\n            ) : (\n              <ItemGroup className=\"gap-0\">\n                {invitations.map((invitation, index) => (\n                  <Fragment key={invitation.id}>\n                    {index > 0 && <ItemSeparator />}\n                    <UserInvitationRow invitation={invitation} />\n                  </Fragment>\n                ))}\n              </ItemGroup>\n            )}\n          </CardContent>\n        </Card>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/user-invitations.tsx"
    },
    {
      "path": "src/components/auth/organization/user-invitation-row.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAcceptInvitation,\n  useAuth,\n  useAuthPlugin,\n  useRejectInvitation\n} from \"@better-auth-ui/react\"\nimport type { Invitation } from \"better-auth/client\"\nimport { Check, Clock, X } from \"lucide-react\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Item,\n  ItemActions,\n  ItemContent,\n  ItemDescription,\n  ItemMedia,\n  ItemTitle\n} from \"@/components/ui/item\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\n\nexport type UserInvitationRowProps = {\n  invitation: Invitation & { organizationName?: string }\n}\n\n/**\n * Single invitation row with accept/reject actions for the current user.\n */\nexport function UserInvitationRow({ invitation }: UserInvitationRowProps) {\n  const { authClient } = useAuth()\n  const { localization: organizationLocalization, roles } =\n    useAuthPlugin(organizationPlugin)\n\n  const { mutate: acceptInvitation, isPending: isAccepting } =\n    useAcceptInvitation(authClient as OrganizationAuthClient)\n\n  const { mutate: rejectInvitation, isPending: isRejecting } =\n    useRejectInvitation(authClient as OrganizationAuthClient)\n\n  return (\n    <Item>\n      <ItemMedia variant=\"icon\">\n        <Clock />\n      </ItemMedia>\n      <ItemContent>\n        <ItemTitle>\n          {invitation.organizationName}\n          <Badge variant=\"secondary\">\n            {roles?.[invitation.role] ?? invitation.role}\n          </Badge>\n        </ItemTitle>\n        <ItemDescription>\n          {new Date(invitation.createdAt).toLocaleString(undefined, {\n            dateStyle: \"medium\",\n            timeStyle: \"short\"\n          })}\n        </ItemDescription>\n      </ItemContent>\n      <ItemActions>\n        <Button\n          variant=\"outline\"\n          size=\"sm\"\n          disabled={isAccepting || isRejecting}\n          onClick={() => acceptInvitation({ invitationId: invitation.id })}\n        >\n          {isAccepting ? <Spinner /> : <Check />}\n\n          {organizationLocalization.accept}\n        </Button>\n\n        <Button\n          variant=\"outline\"\n          size=\"icon\"\n          className=\"size-8 text-destructive\"\n          disabled={isAccepting || isRejecting}\n          onClick={() => rejectInvitation({ invitationId: invitation.id })}\n          aria-label={organizationLocalization.rejectInvitation}\n        >\n          {isRejecting ? <Spinner /> : <X />}\n        </Button>\n      </ItemActions>\n    </Item>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/user-invitation-row.tsx"
    },
    {
      "path": "src/components/auth/organization/user-invitation-row-skeleton.tsx",
      "content": "\"use client\"\n\nimport { Item, ItemContent, ItemMedia } from \"@/components/ui/item\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\n\n/**\n * Placeholder row matching `UserInvitationRow` while invitations load.\n */\nexport function UserInvitationRowSkeleton() {\n  return (\n    <Item>\n      <ItemMedia>\n        <Skeleton className=\"size-10 shrink-0 rounded-md\" />\n      </ItemMedia>\n      <ItemContent>\n        <Skeleton className=\"h-4 w-40 rounded-md\" />\n        <Skeleton className=\"h-3 w-28 rounded-md\" />\n      </ItemContent>\n    </Item>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/user-invitation-row-skeleton.tsx"
    },
    {
      "path": "src/components/auth/organization/user-invitations-empty.tsx",
      "content": "\"use client\"\n\nimport { useAuthPlugin } from \"@better-auth-ui/react\"\nimport { Send } from \"lucide-react\"\n\nimport {\n  Empty,\n  EmptyDescription,\n  EmptyHeader,\n  EmptyMedia,\n  EmptyTitle\n} from \"@/components/ui/empty\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\n\n/**\n * Empty state for `UserInvitations`.\n */\nexport function UserInvitationsEmpty() {\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  return (\n    <Empty>\n      <EmptyHeader>\n        <EmptyMedia variant=\"icon\">\n          <Send />\n        </EmptyMedia>\n        <EmptyTitle>{organizationLocalization.noInvitations}</EmptyTitle>\n        <EmptyDescription>\n          {organizationLocalization.userInvitationsEmptyDescription}\n        </EmptyDescription>\n      </EmptyHeader>\n    </Empty>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/user-invitations-empty.tsx"
    },
    {
      "path": "src/components/auth/organization/create-organization-dialog.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useCreateOrganization\n} from \"@better-auth-ui/react\"\nimport { Briefcase } from \"lucide-react\"\nimport { type SyntheticEvent, useEffect, useState } from \"react\"\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle\n} from \"@/components/ui/dialog\"\nimport { Field, FieldError, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { SlugField, sanitizeSlug } from \"./slug-field\"\n\n/** Props for the `CreateOrganizationDialog` component. */\nexport type CreateOrganizationDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n}\n\nexport function CreateOrganizationDialog({\n  open,\n  onOpenChange\n}: CreateOrganizationDialogProps) {\n  const { authClient, localization } = useAuth()\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  const [name, setName] = useState(\"\")\n  const [slug, setSlug] = useState(\"\")\n  const [slugEdited, setSlugEdited] = useState(false)\n  const [nameError, setNameError] = useState<string>()\n\n  const { mutate: createOrganization, isPending: isCreating } =\n    useCreateOrganization(authClient as OrganizationAuthClient, {\n      onSuccess: () => onOpenChange(false)\n    })\n\n  const handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => {\n    e.preventDefault()\n    createOrganization({ name, slug })\n  }\n\n  useEffect(() => {\n    if (!open) {\n      setSlug(\"\")\n      setName(\"\")\n      setSlugEdited(false)\n      setNameError(undefined)\n    }\n  }, [open])\n\n  useEffect(() => {\n    if (slugEdited) return\n    setSlug(sanitizeSlug(name))\n  }, [name, slugEdited])\n\n  return (\n    <Dialog open={open} onOpenChange={onOpenChange}>\n      <DialogContent>\n        <form onSubmit={handleSubmit} className=\"flex flex-col gap-6\">\n          <DialogHeader>\n            <DialogTitle>\n              <Briefcase />\n              {organizationLocalization.createOrganization}\n            </DialogTitle>\n\n            <DialogDescription>\n              {organizationLocalization.organizationsDescription}\n            </DialogDescription>\n          </DialogHeader>\n\n          <div className=\"flex flex-col gap-4\">\n            <Field data-invalid={!!nameError}>\n              <FieldLabel htmlFor=\"create-organization-name\">\n                {organizationLocalization.name}\n              </FieldLabel>\n\n              <Input\n                id=\"create-organization-name\"\n                name=\"name\"\n                autoFocus\n                required\n                placeholder={organizationLocalization.namePlaceholder}\n                value={name}\n                onChange={(e) => {\n                  setName(e.target.value)\n                  setNameError(undefined)\n                }}\n                onInvalid={(e) => {\n                  e.preventDefault()\n                  setNameError(localization.auth.fieldRequired)\n                }}\n                aria-invalid={!!nameError}\n                disabled={isCreating}\n              />\n\n              <FieldError>{nameError}</FieldError>\n            </Field>\n\n            <SlugField\n              id=\"create-organization-slug\"\n              value={slug}\n              onChange={(value) => {\n                setSlug(value)\n                setSlugEdited(true)\n              }}\n              disabled={isCreating}\n            />\n          </div>\n\n          <DialogFooter>\n            <DialogClose\n              className={buttonVariants({ variant: \"outline\" })}\n              disabled={isCreating}\n              type=\"button\"\n            >\n              {localization.settings.cancel}\n            </DialogClose>\n\n            <Button type=\"submit\" disabled={isCreating}>\n              {isCreating && <Spinner />}\n\n              {organizationLocalization.createOrganization}\n            </Button>\n          </DialogFooter>\n        </form>\n      </DialogContent>\n    </Dialog>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/create-organization-dialog.tsx"
    },
    {
      "path": "src/components/auth/organization/invite-member-dialog.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useInviteMember\n} from \"@better-auth-ui/react\"\nimport { UserPlus } from \"lucide-react\"\nimport { type SyntheticEvent, useEffect, useState } from \"react\"\nimport { toast } from \"sonner\"\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle\n} from \"@/components/ui/dialog\"\nimport { Field, FieldError, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue\n} from \"@/components/ui/select\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\n\n/** Props for the `InviteMemberDialog` component. */\nexport type InviteMemberDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n}\n\nconst pickDefaultRole = (keys: string[]) =>\n  keys.includes(\"member\") ? \"member\" : (keys.at(-1) ?? \"\")\n\n/**\n * Render a dialog for inviting a member to the organization.\n */\nexport function InviteMemberDialog({\n  open,\n  onOpenChange\n}: InviteMemberDialogProps) {\n  const { authClient, localization } = useAuth()\n  const { localization: organizationLocalization, roles } =\n    useAuthPlugin(organizationPlugin)\n\n  const [role, setRole] = useState(() => pickDefaultRole(Object.keys(roles)))\n  const [emailError, setEmailError] = useState<string>()\n\n  useEffect(() => {\n    setRole((current) => {\n      const keys = Object.keys(roles)\n      return keys.includes(current) ? current : pickDefaultRole(keys)\n    })\n  }, [roles])\n\n  useEffect(() => {\n    if (!open) setEmailError(undefined)\n  }, [open])\n\n  const { mutate: inviteMember, isPending: isInviting } = useInviteMember(\n    authClient as OrganizationAuthClient,\n    {\n      onSuccess: () => {\n        onOpenChange(false)\n        toast.success(organizationLocalization.inviteMemberSuccess)\n      }\n    }\n  )\n\n  const isRoleValid = Object.keys(roles).includes(role)\n\n  const handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => {\n    e.preventDefault()\n\n    if (!isRoleValid) return\n\n    const formData = new FormData(e.target as HTMLFormElement)\n    const email = formData.get(\"email\") as string\n\n    inviteMember({\n      email: email.trim(),\n      role: role as Parameters<typeof inviteMember>[0][\"role\"]\n    })\n  }\n\n  return (\n    <Dialog open={open} onOpenChange={onOpenChange}>\n      <DialogContent>\n        <form onSubmit={handleSubmit} className=\"flex flex-col gap-6\">\n          <DialogHeader>\n            <DialogTitle>\n              <UserPlus />\n              {organizationLocalization.inviteMember}\n            </DialogTitle>\n\n            <DialogDescription>\n              {organizationLocalization.inviteMemberDescription}\n            </DialogDescription>\n          </DialogHeader>\n\n          <div className=\"flex flex-col gap-4\">\n            <Field data-invalid={!!emailError}>\n              <FieldLabel htmlFor=\"invite-member-email\">\n                {localization.auth.email}\n              </FieldLabel>\n\n              <Input\n                id=\"invite-member-email\"\n                name=\"email\"\n                type=\"email\"\n                autoFocus\n                required\n                placeholder={localization.auth.email}\n                disabled={isInviting}\n                onChange={() => setEmailError(undefined)}\n                onInvalid={(e) => {\n                  e.preventDefault()\n                  const el = e.target as HTMLInputElement\n                  const msg = el.validity.valueMissing\n                    ? localization.auth.fieldRequired\n                    : localization.auth.invalidEmail\n                  setEmailError(msg)\n                }}\n                aria-invalid={!!emailError}\n              />\n\n              <FieldError>{emailError}</FieldError>\n            </Field>\n\n            <Field>\n              <FieldLabel htmlFor=\"invite-member-role\">\n                {organizationLocalization.role}\n              </FieldLabel>\n\n              <Select\n                value={role}\n                onValueChange={(value) => setRole(value ?? \"\")}\n                disabled={isInviting}\n              >\n                <SelectTrigger id=\"invite-member-role\" className=\"w-full\">\n                  <SelectValue />\n                </SelectTrigger>\n\n                <SelectContent>\n                  {Object.entries(roles).map(([key, label]) => (\n                    <SelectItem key={key} value={key}>\n                      {label}\n                    </SelectItem>\n                  ))}\n                </SelectContent>\n              </Select>\n\n              <FieldError />\n            </Field>\n          </div>\n\n          <DialogFooter>\n            <DialogClose\n              className={buttonVariants({ variant: \"outline\" })}\n              disabled={isInviting}\n              type=\"button\"\n            >\n              {localization.settings.cancel}\n            </DialogClose>\n\n            <Button type=\"submit\" disabled={isInviting || !isRoleValid}>\n              {isInviting && <Spinner />}\n\n              {organizationLocalization.inviteMember}\n            </Button>\n          </DialogFooter>\n        </form>\n      </DialogContent>\n    </Dialog>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/invite-member-dialog.tsx"
    },
    {
      "path": "src/components/auth/organization/delete-organization-dialog.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useDeleteOrganization\n} from \"@better-auth-ui/react\"\nimport type { Organization } from \"better-auth/client\"\nimport { TriangleAlert } from \"lucide-react\"\nimport type { SyntheticEvent } from \"react\"\nimport { toast } from \"sonner\"\n\nimport {\n  AlertDialog,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogMedia,\n  AlertDialogTitle\n} from \"@/components/ui/alert-dialog\"\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { OrganizationView } from \"./organization-view\"\n\nexport type DeleteOrganizationDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  organization: Organization\n}\n\nexport function DeleteOrganizationDialog({\n  open,\n  onOpenChange,\n  organization\n}: DeleteOrganizationDialogProps) {\n  const { authClient, basePaths, localization, navigate } = useAuth()\n  const {\n    localization: organizationLocalization,\n    viewPaths: organizationPluginViewPaths\n  } = useAuthPlugin(organizationPlugin)\n\n  const { mutate: deleteOrganization, isPending } = useDeleteOrganization(\n    authClient as OrganizationAuthClient,\n    {\n      onSuccess: () => {\n        onOpenChange(false)\n        toast.success(organizationLocalization.organizationDeleted)\n\n        navigate({\n          to: `${basePaths.settings}/${organizationPluginViewPaths.settings.organizations}`,\n          replace: true\n        })\n      }\n    }\n  )\n\n  function handleSubmit(e: SyntheticEvent<HTMLFormElement>) {\n    e.preventDefault()\n    deleteOrganization({ organizationId: organization.id })\n  }\n\n  return (\n    <AlertDialog open={open} onOpenChange={onOpenChange}>\n      <AlertDialogContent>\n        <form onSubmit={handleSubmit} className=\"flex flex-col gap-6\">\n          <AlertDialogHeader>\n            <AlertDialogMedia className=\"bg-destructive/10 text-destructive\">\n              <TriangleAlert />\n            </AlertDialogMedia>\n\n            <AlertDialogTitle>\n              {organizationLocalization.deleteOrganization}\n            </AlertDialogTitle>\n\n            <AlertDialogDescription>\n              {organizationLocalization.deleteOrganizationDescription}\n            </AlertDialogDescription>\n          </AlertDialogHeader>\n\n          <Card>\n            <CardContent>\n              <OrganizationView organization={organization} hideRole />\n            </CardContent>\n          </Card>\n\n          <AlertDialogFooter>\n            <AlertDialogCancel disabled={isPending}>\n              {localization.settings.cancel}\n            </AlertDialogCancel>\n\n            <Button type=\"submit\" variant=\"destructive\" disabled={isPending}>\n              {isPending && <Spinner />}\n\n              {organizationLocalization.deleteOrganization}\n            </Button>\n          </AlertDialogFooter>\n        </form>\n      </AlertDialogContent>\n    </AlertDialog>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/delete-organization-dialog.tsx"
    },
    {
      "path": "src/components/auth/organization/delete-organization-skeleton.tsx",
      "content": "\"use client\"\n\nimport { Skeleton } from \"@/components/ui/skeleton\"\n\n/**\n * Placeholder matching `DeleteOrganization` while the delete permission resolves.\n */\nexport function DeleteOrganizationSkeleton() {\n  return (\n    <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n      <div className=\"flex flex-col gap-1\">\n        <Skeleton className=\"h-3.5 w-40 rounded-md\" />\n        <Skeleton className=\"h-3 w-64 rounded-md\" />\n      </div>\n\n      <Skeleton className=\"h-8 w-36 shrink-0 rounded-md\" />\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/delete-organization-skeleton.tsx"
    },
    {
      "path": "src/components/auth/organization/delete-organization.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useActiveOrganization,\n  useAuth,\n  useAuthPlugin,\n  useHasPermission\n} from \"@better-auth-ui/react\"\nimport { useState } from \"react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { DeleteOrganizationDialog } from \"./delete-organization-dialog\"\nimport { DeleteOrganizationSkeleton } from \"./delete-organization-skeleton\"\n\n/**\n * Danger-zone row to delete the active organization. Hidden for members without\n * the `organization:delete` permission.\n */\nexport function DeleteOrganization() {\n  const { authClient } = useAuth()\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  const { data: activeOrganization } = useActiveOrganization(\n    authClient as OrganizationAuthClient\n  )\n\n  const { data: permission, isPending: permissionPending } = useHasPermission(\n    authClient as OrganizationAuthClient,\n    {\n      permissions: { organization: [\"delete\"] }\n    }\n  )\n\n  const [confirmOpen, setConfirmOpen] = useState(false)\n\n  if (permissionPending) {\n    return <DeleteOrganizationSkeleton />\n  }\n\n  if (!permission?.success) {\n    return null\n  }\n\n  return (\n    <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n      <div>\n        <p className=\"text-sm font-medium leading-tight\">\n          {organizationLocalization.deleteOrganization}\n        </p>\n\n        <p className=\"text-muted-foreground mt-0.5 text-xs\">\n          {organizationLocalization.deleteOrganizationDescription}\n        </p>\n      </div>\n\n      <Button\n        disabled={!activeOrganization}\n        size=\"sm\"\n        variant=\"outline\"\n        className=\"text-destructive\"\n        onClick={() => setConfirmOpen(true)}\n      >\n        {organizationLocalization.deleteOrganization}\n      </Button>\n\n      {activeOrganization && (\n        <DeleteOrganizationDialog\n          open={confirmOpen}\n          onOpenChange={setConfirmOpen}\n          organization={activeOrganization}\n        />\n      )}\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/delete-organization.tsx"
    },
    {
      "path": "src/components/auth/organization/leave-organization-dialog.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useLeaveOrganization\n} from \"@better-auth-ui/react\"\nimport type { Organization } from \"better-auth/client\"\nimport { LogOut } from \"lucide-react\"\nimport { toast } from \"sonner\"\n\nimport {\n  AlertDialog,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogMedia,\n  AlertDialogTitle\n} from \"@/components/ui/alert-dialog\"\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { OrganizationView } from \"./organization-view\"\n\nexport type LeaveOrganizationDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  organization: Organization\n}\n\nexport function LeaveOrganizationDialog({\n  open,\n  onOpenChange,\n  organization\n}: LeaveOrganizationDialogProps) {\n  const { authClient, basePaths, localization, navigate } = useAuth()\n  const {\n    localization: organizationLocalization,\n    viewPaths: organizationPluginViewPaths\n  } = useAuthPlugin(organizationPlugin)\n\n  const { mutate: leaveOrganization, isPending } = useLeaveOrganization(\n    authClient as OrganizationAuthClient,\n    {\n      onSuccess: () => {\n        onOpenChange(false)\n        toast.success(organizationLocalization.leftOrganization)\n\n        navigate({\n          to: `${basePaths.settings}/${organizationPluginViewPaths.settings.organizations}`,\n          replace: true\n        })\n      }\n    }\n  )\n\n  return (\n    <AlertDialog open={open} onOpenChange={onOpenChange}>\n      <AlertDialogContent>\n        <AlertDialogHeader>\n          <AlertDialogMedia className=\"bg-destructive/10 text-destructive\">\n            <LogOut />\n          </AlertDialogMedia>\n\n          <AlertDialogTitle>\n            {organizationLocalization.leaveOrganization}\n          </AlertDialogTitle>\n\n          <AlertDialogDescription>\n            {organizationLocalization.leaveOrganizationDescription}\n          </AlertDialogDescription>\n        </AlertDialogHeader>\n\n        <Card>\n          <CardContent>\n            <OrganizationView organization={organization} hideRole />\n          </CardContent>\n        </Card>\n\n        <AlertDialogFooter>\n          <AlertDialogCancel disabled={isPending}>\n            {localization.settings.cancel}\n          </AlertDialogCancel>\n\n          <Button\n            variant=\"destructive\"\n            disabled={isPending}\n            onClick={() =>\n              leaveOrganization({ organizationId: organization.id })\n            }\n          >\n            {isPending && <Spinner />}\n\n            {organizationLocalization.leaveOrganization}\n          </Button>\n        </AlertDialogFooter>\n      </AlertDialogContent>\n    </AlertDialog>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/leave-organization-dialog.tsx"
    },
    {
      "path": "src/components/auth/organization/leave-organization.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useActiveOrganization,\n  useAuth,\n  useAuthPlugin\n} from \"@better-auth-ui/react\"\nimport { useState } from \"react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { LeaveOrganizationDialog } from \"./leave-organization-dialog\"\n\n/**\n * Danger-zone row to leave the active organization.\n */\nexport function LeaveOrganization() {\n  const { authClient } = useAuth()\n  const { localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  const { data: activeOrganization } = useActiveOrganization(\n    authClient as OrganizationAuthClient\n  )\n\n  const [confirmOpen, setConfirmOpen] = useState(false)\n\n  return (\n    <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n      <div>\n        <p className=\"text-sm font-medium leading-tight\">\n          {organizationLocalization.leaveOrganization}\n        </p>\n\n        <p className=\"text-muted-foreground mt-0.5 text-xs\">\n          {organizationLocalization.leaveOrganizationDescription}\n        </p>\n      </div>\n\n      <Button\n        disabled={!activeOrganization}\n        size=\"sm\"\n        variant=\"outline\"\n        className=\"text-destructive\"\n        onClick={() => setConfirmOpen(true)}\n      >\n        {organizationLocalization.leaveOrganization}\n      </Button>\n\n      {activeOrganization && (\n        <LeaveOrganizationDialog\n          open={confirmOpen}\n          onOpenChange={setConfirmOpen}\n          organization={activeOrganization}\n        />\n      )}\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/leave-organization.tsx"
    },
    {
      "path": "src/components/auth/organization/remove-member-dialog.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useRemoveMember\n} from \"@better-auth-ui/react\"\nimport type { Member, User } from \"better-auth/client\"\nimport { Trash2 } from \"lucide-react\"\nimport { toast } from \"sonner\"\n\nimport {\n  AlertDialog,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogMedia,\n  AlertDialogTitle\n} from \"@/components/ui/alert-dialog\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { UserView } from \"../user/user-view\"\n\nexport type RemoveMemberDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  member: Member & { user: Partial<User> }\n}\n\nexport function RemoveMemberDialog({\n  open,\n  onOpenChange,\n  member\n}: RemoveMemberDialogProps) {\n  const { authClient, localization } = useAuth()\n  const { localization: organizationLocalization, roles } =\n    useAuthPlugin(organizationPlugin)\n\n  const { mutate: removeMember, isPending } = useRemoveMember(\n    authClient as OrganizationAuthClient,\n    {\n      onSuccess: () => {\n        onOpenChange(false)\n        toast.success(organizationLocalization.memberRemoved)\n      }\n    }\n  )\n\n  return (\n    <AlertDialog open={open} onOpenChange={onOpenChange}>\n      <AlertDialogContent>\n        <AlertDialogHeader>\n          <AlertDialogMedia className=\"bg-destructive/10 text-destructive\">\n            <Trash2 />\n          </AlertDialogMedia>\n\n          <AlertDialogTitle>\n            {organizationLocalization.removeMember}\n          </AlertDialogTitle>\n\n          <AlertDialogDescription>\n            {organizationLocalization.removeMemberWarning}\n          </AlertDialogDescription>\n        </AlertDialogHeader>\n\n        <Card>\n          <CardContent className=\"flex flex-row items-center justify-between gap-2\">\n            <UserView user={member.user} />\n\n            <Badge variant=\"outline\">\n              {roles?.[member.role] ?? member.role}\n            </Badge>\n          </CardContent>\n        </Card>\n\n        <AlertDialogFooter>\n          <AlertDialogCancel disabled={isPending}>\n            {localization.settings.cancel}\n          </AlertDialogCancel>\n\n          <Button\n            variant=\"destructive\"\n            disabled={isPending}\n            onClick={() =>\n              removeMember({\n                memberIdOrEmail: member.id,\n                organizationId: member.organizationId\n              })\n            }\n          >\n            {isPending && <Spinner />}\n\n            {organizationLocalization.removeMember}\n          </Button>\n        </AlertDialogFooter>\n      </AlertDialogContent>\n    </AlertDialog>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/remove-member-dialog.tsx"
    },
    {
      "path": "src/components/auth/organization/change-organization-logo.tsx",
      "content": "\"use client\"\n\nimport { fileToBase64 } from \"@better-auth-ui/core\"\nimport {\n  type OrganizationAuthClient,\n  useActiveOrganization,\n  useAuth,\n  useAuthPlugin,\n  useUpdateOrganization\n} from \"@better-auth-ui/react\"\nimport { Trash2, Upload } from \"lucide-react\"\nimport { type ChangeEvent, useRef, useState } from \"react\"\nimport { toast } from \"sonner\"\n\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger\n} from \"@/components/ui/dropdown-menu\"\nimport { Label } from \"@/components/ui/label\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport { OrganizationLogo } from \"./organization-logo\"\n\nexport type ChangeOrganizationLogoProps = {\n  className?: string\n}\n\nexport function ChangeOrganizationLogo({\n  className\n}: ChangeOrganizationLogoProps) {\n  const { authClient } = useAuth()\n  const { logo, localization: organizationLocalization } =\n    useAuthPlugin(organizationPlugin)\n\n  const { data: activeOrganization, isPending: activeOrganizationPending } =\n    useActiveOrganization(authClient as OrganizationAuthClient)\n\n  const { mutate: updateOrganization, isPending: updatePending } =\n    useUpdateOrganization(authClient as OrganizationAuthClient)\n\n  const fileInputRef = useRef<HTMLInputElement>(null)\n  const [isUploading, setIsUploading] = useState(false)\n  const [isDeleting, setIsDeleting] = useState(false)\n\n  const isPending = updatePending || isUploading || isDeleting\n\n  async function handleFileChange(e: ChangeEvent<HTMLInputElement>) {\n    const file = e.target.files?.[0]\n    if (!file || !activeOrganization) return\n\n    e.target.value = \"\"\n\n    setIsUploading(true)\n\n    try {\n      const resized =\n        (await logo.resize?.(file, logo.size, logo.extension)) || file\n\n      const image =\n        (await logo.upload?.(resized)) || (await fileToBase64(resized))\n\n      updateOrganization(\n        { data: { logo: image } },\n        {\n          onSuccess: () =>\n            toast.success(organizationLocalization.logoChangedSuccess),\n          onSettled: () => setIsUploading(false)\n        }\n      )\n    } catch (error) {\n      setIsUploading(false)\n      if (error instanceof Error) {\n        toast.error(error.message)\n      }\n    }\n  }\n\n  async function handleDelete() {\n    const currentLogo = activeOrganization?.logo\n\n    updateOrganization(\n      { data: { logo: \"\" } },\n      {\n        onSuccess: async () => {\n          if (!currentLogo) {\n            toast.success(organizationLocalization.logoDeletedSuccess)\n            return\n          }\n\n          setIsDeleting(true)\n          try {\n            await logo.delete?.(currentLogo)\n            toast.success(organizationLocalization.logoDeletedSuccess)\n          } catch (error) {\n            if (error instanceof Error) {\n              toast.error(error.message)\n            }\n          } finally {\n            setIsDeleting(false)\n          }\n        }\n      }\n    )\n  }\n\n  if (!logo.enabled) {\n    return null\n  }\n\n  return (\n    <div className={cn(\"flex flex-col gap-1\", className)}>\n      <Label aria-disabled={!activeOrganization}>\n        {organizationLocalization.logo}\n      </Label>\n\n      <input\n        ref={fileInputRef}\n        type=\"file\"\n        accept=\"image/*\"\n        className=\"hidden\"\n        onChange={handleFileChange}\n      />\n\n      <div className=\"flex items-center gap-4\">\n        <Button\n          type=\"button\"\n          variant=\"ghost\"\n          size=\"icon\"\n          className=\"h-auto w-auto rounded-full p-0\"\n          disabled={!activeOrganization || isPending}\n          onClick={() => fileInputRef.current?.click()}\n        >\n          <OrganizationLogo\n            size=\"lg\"\n            isPending={activeOrganizationPending}\n            organization={activeOrganization}\n          />\n        </Button>\n\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            className={cn(buttonVariants({ size: \"sm\", variant: \"secondary\" }))}\n            disabled={!activeOrganization || isPending}\n          >\n            {isPending && <Spinner />}\n\n            {organizationLocalization.changeLogo}\n          </DropdownMenuTrigger>\n\n          <DropdownMenuContent align=\"start\" className=\"min-w-fit\">\n            <DropdownMenuItem onClick={() => fileInputRef.current?.click()}>\n              <Upload className=\"text-muted-foreground\" />\n\n              {organizationLocalization.uploadLogo}\n            </DropdownMenuItem>\n\n            <DropdownMenuItem\n              disabled={!activeOrganization?.logo}\n              onClick={handleDelete}\n              variant=\"destructive\"\n            >\n              <Trash2 />\n\n              {organizationLocalization.deleteLogo}\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/change-organization-logo.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-logo.tsx",
      "content": "\"use client\"\n\nimport type { Organization } from \"better-auth/client\"\nimport { Briefcase } from \"lucide-react\"\nimport type { ComponentProps, CSSProperties, ReactNode } from \"react\"\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport { cn } from \"@/lib/utils\"\n\nexport type OrganizationLogoSize = \"sm\" | \"md\" | \"lg\"\n\nexport type OrganizationLogoProps = {\n  className?: string\n  fallback?: ReactNode\n  isPending?: boolean\n  organization?: Partial<Organization>\n  size?: OrganizationLogoSize\n}\n\nconst sizeClasses: Record<OrganizationLogoSize, string> = {\n  sm: \"size-8\",\n  md: \"size-10\",\n  lg: \"size-12\"\n}\n\nconst fallbackTextClasses: Record<OrganizationLogoSize, string> = {\n  sm: \"text-sm\",\n  md: \"text-base\",\n  lg: \"text-xl\"\n}\n\nexport function OrganizationLogo({\n  className,\n  fallback,\n  isPending,\n  organization,\n  size = \"sm\",\n  style,\n  ...props\n}: OrganizationLogoProps &\n  Omit<ComponentProps<typeof Avatar>, \"children\" | \"size\" | \"style\"> & {\n    style?: CSSProperties\n  }) {\n  if (isPending && !organization) {\n    return (\n      <Skeleton\n        className={cn(\"rounded-full\", sizeClasses[size], className)}\n        style={style}\n      />\n    )\n  }\n\n  const initials = organization?.name?.slice(0, 2).toUpperCase()\n  const normalizedLogo = organization?.logo?.trim() || undefined\n\n  return (\n    <Avatar\n      className={cn(\"rounded-full\", sizeClasses[size], className)}\n      style={style}\n      {...props}\n    >\n      <AvatarImage\n        alt={organization?.name ?? \"Organization\"}\n        src={normalizedLogo}\n      />\n\n      <AvatarFallback\n        className={cn(\"text-muted-foreground!\", fallbackTextClasses[size])}\n      >\n        {fallback || initials || <Briefcase className=\"size-4\" />}\n      </AvatarFallback>\n    </Avatar>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-logo.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-view.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useActiveOrganization,\n  useAuth,\n  useAuthPlugin,\n  useListOrganizationMembers,\n  useSession\n} from \"@better-auth-ui/react\"\nimport type { Organization } from \"better-auth/client\"\nimport type { ComponentProps } from \"react\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\nimport { cn } from \"@/lib/utils\"\nimport {\n  OrganizationLogo,\n  type OrganizationLogoSize\n} from \"./organization-logo\"\nimport { OrganizationViewSkeleton } from \"./organization-view-skeleton\"\n\nexport type OrganizationViewProps = {\n  className?: string\n  isPending?: boolean\n  size?: OrganizationLogoSize\n  hideRole?: boolean\n  hideSlug?: boolean\n  organization?: Partial<Organization>\n}\n\n/**\n * Compact organization row: logo, primary name, secondary slug — analogous to `UserView`.\n */\nexport function OrganizationView({\n  className,\n  isPending,\n  size = \"md\",\n  hideSlug,\n  hideRole,\n  organization,\n  ...props\n}: OrganizationViewProps & ComponentProps<\"div\">) {\n  const { authClient } = useAuth()\n  const { roles, slugPrefix } = useAuthPlugin(organizationPlugin)\n\n  const { data: session } = useSession(authClient)\n\n  const { data: activeOrganization, isPending: activeOrganizationPending } =\n    useActiveOrganization(authClient as OrganizationAuthClient, {\n      enabled: !organization && !isPending\n    })\n\n  const resolvedOrganization = organization ?? activeOrganization\n\n  const { data: membersList, isPending: membersPending } =\n    useListOrganizationMembers(authClient as OrganizationAuthClient, {\n      query: {\n        organizationId: resolvedOrganization?.id\n      },\n      enabled: !!resolvedOrganization?.id && !hideRole\n    })\n\n  const membership = membersList?.members?.find(\n    (member) => member.userId === session?.user.id\n  )\n\n  if (\n    isPending ||\n    (!organization && activeOrganizationPending) ||\n    (!hideRole && !!resolvedOrganization?.id && membersPending)\n  ) {\n    return (\n      <OrganizationViewSkeleton\n        className={className}\n        hideSlug={hideSlug}\n        size={size}\n        {...props}\n      />\n    )\n  }\n\n  return (\n    <div\n      className={cn(\"flex min-w-0 items-center gap-2\", className)}\n      {...props}\n    >\n      <OrganizationLogo\n        organization={resolvedOrganization}\n        className={size === \"sm\" ? \"size-5\" : undefined}\n        size={size === \"lg\" ? \"md\" : \"sm\"}\n      />\n\n      <div className=\"flex min-w-0 flex-col\">\n        <div className=\"flex min-w-0 items-center gap-2\">\n          <p className=\"truncate text-sm font-medium leading-tight text-foreground\">\n            {resolvedOrganization?.name}\n          </p>\n\n          {!hideRole && !!membership && (\n            <Badge variant=\"secondary\" className=\"-my-0.5 shrink-0\">\n              {roles?.[membership.role] ?? membership.role}\n            </Badge>\n          )}\n        </div>\n\n        {!hideSlug && !!resolvedOrganization?.slug && (\n          <p className=\"truncate overflow-x-hidden text-muted-foreground text-xs font-mono leading-tight\">\n            {slugPrefix}\n            {resolvedOrganization.slug}\n          </p>\n        )}\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-view.tsx"
    },
    {
      "path": "src/components/auth/organization/organization-view-skeleton.tsx",
      "content": "\"use client\"\n\nimport type { ComponentProps } from \"react\"\n\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport { cn } from \"@/lib/utils\"\nimport {\n  OrganizationLogo,\n  type OrganizationLogoSize\n} from \"./organization-logo\"\n\nexport type OrganizationViewSkeletonProps = {\n  className?: string\n  hideSlug?: boolean\n  size?: OrganizationLogoSize\n}\n\n/**\n * Placeholder matching `OrganizationView` while organization data loads.\n */\nexport function OrganizationViewSkeleton({\n  className,\n  hideSlug,\n  size = \"md\",\n  ...props\n}: OrganizationViewSkeletonProps & ComponentProps<\"div\">) {\n  return (\n    <div\n      className={cn(\"flex min-w-0 items-center gap-2\", className)}\n      {...props}\n    >\n      <OrganizationLogo\n        isPending\n        className={size === \"sm\" ? \"size-5\" : undefined}\n        size={size === \"lg\" ? \"md\" : \"sm\"}\n      />\n\n      <div className=\"flex flex-col min-w-0 gap-1\">\n        <Skeleton className=\"h-3.5 w-20 rounded-md\" />\n\n        {!hideSlug && <Skeleton className=\"h-3 w-28 rounded-md\" />}\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/organization-view-skeleton.tsx"
    },
    {
      "path": "src/components/auth/organization/slug-field.tsx",
      "content": "\"use client\"\n\nimport {\n  type OrganizationAuthClient,\n  useAuth,\n  useAuthPlugin,\n  useCheckSlug\n} from \"@better-auth-ui/react\"\nimport { useDebouncer } from \"@tanstack/react-pacer\"\nimport { Check, X } from \"lucide-react\"\nimport { useEffect, useState } from \"react\"\n\nimport { Field, FieldError, FieldLabel } from \"@/components/ui/field\"\nimport {\n  InputGroup,\n  InputGroupAddon,\n  InputGroupInput\n} from \"@/components/ui/input-group\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { organizationPlugin } from \"@/lib/auth/organization-plugin\"\n\n/** Props for the `SlugField` component. */\nexport type SlugFieldProps = {\n  value: string\n  onChange: (value: string) => void\n  currentSlug?: string\n  disabled?: boolean\n  id?: string\n}\n\n/**\n * Sanitize a slug value so it only contains lowercase alphanumeric characters\n * and dashes. Runs of disallowed characters are collapsed to a single dash, but\n * leading/trailing dashes are preserved while the user is still typing.\n */\nexport function sanitizeSlug(value: string) {\n  return value.toLowerCase().replace(/[^a-z0-9]+/g, \"-\")\n}\n\n/**\n * Organization slug field with debounced availability checking.\n */\nexport function SlugField({\n  value,\n  onChange,\n  currentSlug,\n  disabled,\n  id = \"slug\"\n}: SlugFieldProps) {\n  const { authClient, localization: authLocalization } = useAuth()\n  const {\n    localization,\n    checkSlug: checkSlugEnabled,\n    slugPrefix\n  } = useAuthPlugin(organizationPlugin)\n\n  const [slugError, setSlugError] = useState<string>()\n\n  const {\n    mutate: checkSlug,\n    data: checkSlugData,\n    error: checkSlugError,\n    reset: resetCheckSlug\n  } = useCheckSlug(authClient as OrganizationAuthClient)\n\n  const debouncer = useDebouncer(\n    (next: string) => {\n      if (!checkSlugEnabled || !next.trim() || next.trim() === currentSlug)\n        return\n\n      checkSlug({ slug: next.trim() })\n    },\n    { wait: 500 }\n  )\n\n  useEffect(() => {\n    // Clear stale validation errors when the controlled value changes\n    // externally (e.g. the parent resets the form), not just via this\n    // input's onChange.\n    setSlugError(undefined)\n\n    if (!checkSlugEnabled) return\n\n    resetCheckSlug()\n    debouncer.maybeExecute(value)\n  }, [checkSlugEnabled, value, debouncer.maybeExecute, resetCheckSlug])\n\n  return (\n    <Field data-invalid={!!slugError}>\n      <FieldLabel htmlFor={id}>{localization.slug}</FieldLabel>\n\n      <InputGroup>\n        {slugPrefix && (\n          <InputGroupAddon align=\"inline-start\">{slugPrefix}</InputGroupAddon>\n        )}\n\n        <InputGroupInput\n          id={id}\n          name=\"slug\"\n          value={value}\n          onChange={(e) => {\n            onChange(sanitizeSlug(e.target.value))\n            setSlugError(undefined)\n          }}\n          onInvalid={(e) => {\n            e.preventDefault()\n            setSlugError(authLocalization.auth.fieldRequired)\n          }}\n          aria-invalid={!!slugError}\n          placeholder={localization.slugPlaceholder}\n          required\n          disabled={disabled}\n        />\n\n        {checkSlugEnabled && !!value.trim() && value.trim() !== currentSlug && (\n          <InputGroupAddon align=\"inline-end\">\n            {checkSlugData?.status ? (\n              <Check className=\"size-4 text-foreground\" />\n            ) : checkSlugError ? (\n              <X className=\"size-4 text-destructive\" />\n            ) : (\n              <Spinner />\n            )}\n          </InputGroupAddon>\n        )}\n      </InputGroup>\n\n      <FieldError>{slugError}</FieldError>\n    </Field>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/organization/slug-field.tsx"
    }
  ],
  "type": "registry:component"
}