({
value,
onChange,
placeholder = 'Select a secret...',
disabled = false,
className,
onRefresh,
clearable = true,
}: SecretSelectProps)
| 20 | * SecretSelect - A specialized version of LeanSelect for picking secrets. |
| 21 | */ |
| 22 | export function SecretSelect({ |
| 23 | value, |
| 24 | onChange, |
| 25 | placeholder = 'Select a secret...', |
| 26 | disabled = false, |
| 27 | className, |
| 28 | onRefresh, |
| 29 | clearable = true, |
| 30 | }: SecretSelectProps) { |
| 31 | const secrets = useSecretStore((state) => state.secrets); |
| 32 | const loading = useSecretStore((state) => state.loading); |
| 33 | const fetchSecrets = useSecretStore((state) => state.fetchSecrets); |
| 34 | const refreshSecrets = useSecretStore((state) => state.refresh); |
| 35 | const navigate = useNavigate(); |
| 36 | |
| 37 | useEffect(() => { |
| 38 | fetchSecrets().catch((error) => { |
| 39 | console.error('Failed to load secrets:', error); |
| 40 | }); |
| 41 | }, [fetchSecrets]); |
| 42 | |
| 43 | const options: SelectOption[] = secrets.map((s) => ({ |
| 44 | label: getSecretLabel(s), |
| 45 | value: s.id, |
| 46 | description: getSecretDescription(s), |
| 47 | icon: <KeyRound className="h-3.5 w-3.5" />, |
| 48 | })); |
| 49 | |
| 50 | const activeSecret = secrets.find((s) => s.id === value || s.name === value); |
| 51 | |
| 52 | // Determine the display label for when the value isn't matched exactly as an option ID |
| 53 | const selectedLabel = activeSecret |
| 54 | ? getSecretLabel(activeSecret) |
| 55 | : value && !loading |
| 56 | ? /^[0-9a-f]{8}-/i.test(value) |
| 57 | ? `Unknown secret (${value.slice(0, 8)}…)` |
| 58 | : value // Legacy name-based secret reference |
| 59 | : undefined; |
| 60 | |
| 61 | const handleRefresh = async () => { |
| 62 | await refreshSecrets(); |
| 63 | onRefresh?.(); |
| 64 | }; |
| 65 | |
| 66 | const actionButton = ( |
| 67 | <button |
| 68 | type="button" |
| 69 | onClick={() => navigate('/secrets')} |
| 70 | disabled={disabled} |
| 71 | className={cn( |
| 72 | 'p-2 text-muted-foreground border rounded-md bg-background/50 backdrop-blur-sm', |
| 73 | 'hover:bg-muted/40 hover:text-primary transition-all duration-200', |
| 74 | 'focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary/50', |
| 75 | disabled && 'opacity-50 cursor-not-allowed', |
| 76 | )} |
| 77 | title="Manage secrets in store" |
| 78 | > |
| 79 | <ExternalLink className="h-3.5 w-3.5" /> |
nothing calls this directly
no test coverage detected