"use client"; import { useCallback } from "react"; import { Checkbox, Label } from "../../../shadcnui"; import { AVAILABLE_OAUTH_SCOPES, OAuthScopeInfo } from "../interfaces/oauth.interface"; export interface OAuthScopeSelectorProps { /** Currently selected scopes */ value: string[]; /** Called when selection changes */ onChange: (scopes: string[]) => void; /** Available scopes to display (defaults to all) */ availableScopes?: OAuthScopeInfo[]; /** Whether selector is disabled */ disabled?: boolean; /** Error message */ error?: string; /** Label text */ label?: string; } /** * Checkbox selector for OAuth scopes * * @example * ```tsx * const [scopes, setScopes] = useState([]); * * * ``` */ export function OAuthScopeSelector({ value, onChange, availableScopes = AVAILABLE_OAUTH_SCOPES, disabled = false, error, label = "Allowed Scopes", }: OAuthScopeSelectorProps) { const handleToggle = useCallback( (scope: string, checked: boolean) => { if (checked) { onChange([...value, scope]); } else { onChange(value.filter((s) => s !== scope)); } }, [value, onChange], ); // Group scopes by category (before the colon) const groupedScopes = availableScopes.reduce( (acc, scope) => { const [category] = scope.scope.split(":"); const groupName = category === scope.scope ? "General" : category; if (!acc[groupName]) { acc[groupName] = []; } acc[groupName].push(scope); return acc; }, {} as Record, ); return (

Select the permissions your application needs.

{Object.entries(groupedScopes).map(([groupName, scopes]) => (

{groupName}

{scopes.map((scopeInfo) => { const isChecked = value.includes(scopeInfo.scope); const isAdmin = scopeInfo.scope === "admin"; return (
handleToggle(scopeInfo.scope, checked === true)} disabled={disabled} />

{scopeInfo.description}

); })}
))}
{error &&

{error}

}
); }