Files
SuperCharged-Claude-Code-Up…/dexto/packages/webui/components/ui/key-value-editor.tsx
admin b52318eeae feat: Add intelligent auto-router and enhanced integrations
- Add intelligent-router.sh hook for automatic agent routing
- Add AUTO-TRIGGER-SUMMARY.md documentation
- Add FINAL-INTEGRATION-SUMMARY.md documentation
- Complete Prometheus integration (6 commands + 4 tools)
- Complete Dexto integration (12 commands + 5 tools)
- Enhanced Ralph with access to all agents
- Fix /clawd command (removed disable-model-invocation)
- Update hooks.json to v5 with intelligent routing
- 291 total skills now available
- All 21 commands with automatic routing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 00:27:56 +04:00

175 lines
6.3 KiB
TypeScript

import React, { useState } from 'react';
import { Button } from './button';
import { Input } from './input';
import { Label } from './label';
import { Plus, Trash2, Eye, EyeOff } from 'lucide-react';
interface KeyValuePair {
key: string;
value: string;
id: string;
}
interface KeyValueEditorProps {
label?: string;
placeholder?: {
key?: string;
value?: string;
};
pairs: KeyValuePair[];
onChange: (pairs: KeyValuePair[]) => void;
disabled?: boolean;
className?: string;
keyLabel?: string;
valueLabel?: string;
maskSensitiveValues?: boolean;
}
const SENSITIVE_KEY_PATTERNS = [
/\bapi[_-]?key\b/i,
/\bapikey\b/i,
/\bsecret\b/i,
/\btoken\b/i,
/\bpassword\b/i,
/\bauthorization\b/i,
/\bauth[_-]?token\b/i,
/\bbearer\b/i,
/\bcredential\b/i,
/\bclient[_-]?secret\b/i,
];
export function KeyValueEditor({
label = 'Key-Value Pairs',
placeholder = { key: 'Key', value: 'Value' },
pairs,
onChange,
disabled = false,
className = '',
keyLabel = 'Key',
valueLabel = 'Value',
maskSensitiveValues = true,
}: KeyValueEditorProps) {
const [visibleValues, setVisibleValues] = useState<Set<string>>(new Set());
const isSensitiveKey = (key: string): boolean => {
if (!maskSensitiveValues || !key) return false;
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(key));
};
const toggleValueVisibility = (id: string) => {
setVisibleValues((prev) => {
const newSet = new Set(prev);
if (newSet.has(id)) {
newSet.delete(id);
} else {
newSet.add(id);
}
return newSet;
});
};
const addPair = () => {
const newPair: KeyValuePair = {
key: '',
value: '',
id: `kv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
};
onChange([...pairs, newPair]);
};
const removePair = (id: string) => {
const filteredPairs = pairs.filter((pair) => pair.id !== id);
// Allow removing all pairs - don't force an empty pair
onChange(filteredPairs);
};
const updatePair = (id: string, field: 'key' | 'value', newValue: string) => {
onChange(pairs.map((pair) => (pair.id === id ? { ...pair, [field]: newValue } : pair)));
};
return (
<div className={`space-y-3 ${className}`}>
{label && <Label className="text-sm font-medium">{label}</Label>}
<div className="space-y-2">
{/* Header row - only show if there are pairs */}
{pairs.length > 0 && (
<div className="grid grid-cols-12 gap-2 items-center text-xs text-muted-foreground">
<div className="col-span-5">{keyLabel}</div>
<div className="col-span-6">{valueLabel}</div>
<div className="col-span-1"></div>
</div>
)}
{/* Key-value pair rows */}
{pairs.map((pair) => {
const isSensitive = isSensitiveKey(pair.key);
const isVisible = visibleValues.has(pair.id);
return (
<div key={pair.id} className="grid grid-cols-12 gap-2 items-center">
<Input
placeholder={placeholder.key}
value={pair.key}
onChange={(e) => updatePair(pair.id, 'key', e.target.value)}
disabled={disabled}
className="col-span-5"
/>
<div className="col-span-6 relative">
<Input
type={isSensitive && !isVisible ? 'password' : 'text'}
placeholder={placeholder.value}
value={pair.value}
onChange={(e) => updatePair(pair.id, 'value', e.target.value)}
disabled={disabled}
className="pr-10"
/>
{isSensitive && pair.value && (
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => toggleValueVisibility(pair.id)}
disabled={disabled}
className="absolute right-0 top-0 h-full w-10 p-0 hover:bg-transparent"
aria-label={isVisible ? 'Hide value' : 'Show value'}
>
{isVisible ? (
<EyeOff className="h-4 w-4 text-muted-foreground" />
) : (
<Eye className="h-4 w-4 text-muted-foreground" />
)}
</Button>
)}
</div>
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => removePair(pair.id)}
disabled={disabled}
className="col-span-1 h-8 w-8 p-0"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
);
})}
</div>
{/* Add button */}
<Button
type="button"
variant="outline"
size="sm"
onClick={addPair}
disabled={disabled}
className="w-full mt-2"
>
<Plus className="h-4 w-4 mr-2" />
Add {keyLabel}
</Button>
</div>
);
}