5257dfbaab
Co-authored-by: Kandev Agent <agent@kandev.dev> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { IconPlus, IconX } from "@tabler/icons-react";
|
|
import { Button } from "@kandev/ui/button";
|
|
import { Input } from "@kandev/ui/input";
|
|
import type { KeyValue } from "@/lib/settings/types";
|
|
import { generateUUID } from "@/lib/utils";
|
|
import { t } from "@/lib/i18n";
|
|
|
|
type KeyValueInputProps = {
|
|
items: KeyValue[];
|
|
onChange: (items: KeyValue[]) => void;
|
|
keyPlaceholder?: string;
|
|
valuePlaceholder?: string;
|
|
addButtonLabel?: string;
|
|
masked?: boolean;
|
|
};
|
|
|
|
export function KeyValueInput({
|
|
items,
|
|
onChange,
|
|
keyPlaceholder = t("settings:keyValueKeyPlaceholder"),
|
|
valuePlaceholder = t("settings:keyValueValuePlaceholder"),
|
|
addButtonLabel = t("settings:keyValueAddItem"),
|
|
masked = false,
|
|
}: KeyValueInputProps) {
|
|
const handleAdd = () => {
|
|
onChange([...items, { id: generateUUID(), key: "", value: "" }]);
|
|
};
|
|
|
|
const handleRemove = (id: string) => {
|
|
onChange(items.filter((item) => item.id !== id));
|
|
};
|
|
|
|
const handleChange = (id: string, field: "key" | "value", value: string) => {
|
|
onChange(items.map((item) => (item.id === id ? { ...item, [field]: value } : item)));
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-2">
|
|
{items.map((item) => (
|
|
<div key={item.id} className="flex gap-2">
|
|
<Input
|
|
placeholder={keyPlaceholder}
|
|
value={item.key}
|
|
onChange={(e) => handleChange(item.id, "key", e.target.value)}
|
|
className="flex-1"
|
|
/>
|
|
<Input
|
|
type={masked ? "password" : "text"}
|
|
placeholder={valuePlaceholder}
|
|
value={item.value}
|
|
onChange={(e) => handleChange(item.id, "value", e.target.value)}
|
|
className="flex-1"
|
|
/>
|
|
<Button variant="ghost" size="icon" onClick={() => handleRemove(item.id)}>
|
|
<IconX className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
))}
|
|
<Button variant="outline" size="sm" onClick={handleAdd} className="w-full">
|
|
<IconPlus className="h-4 w-4 mr-2" />
|
|
{addButtonLabel}
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|