103 lines
2.4 KiB
TypeScript
103 lines
2.4 KiB
TypeScript
|
|
import React, { useState } from "react";
|
||
|
|
import { Input, Button } from "antd";
|
||
|
|
import { DeleteOutlined } from "@ant-design/icons";
|
||
|
|
|
||
|
|
interface InputListProps {
|
||
|
|
initialValue?: string[];
|
||
|
|
onChange?: (value: string[]) => void;
|
||
|
|
placeholder?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
const InputList: React.FC<InputListProps> = ({
|
||
|
|
initialValue,
|
||
|
|
onChange,
|
||
|
|
placeholder = "请输入内容",
|
||
|
|
}) => {
|
||
|
|
// Internal state management with fallback to initial value or empty array
|
||
|
|
const [inputValues, setInputValues] = useState<string[]>(
|
||
|
|
initialValue && initialValue.length > 0 ? initialValue : [""]
|
||
|
|
);
|
||
|
|
|
||
|
|
// Handle individual input value change
|
||
|
|
const handleInputChange = (index: number, newValue: string) => {
|
||
|
|
const newValues = [...inputValues];
|
||
|
|
newValues[index] = newValue;
|
||
|
|
|
||
|
|
// Update internal state
|
||
|
|
setInputValues(newValues);
|
||
|
|
|
||
|
|
// Call external onChange if provided
|
||
|
|
onChange?.(newValues);
|
||
|
|
};
|
||
|
|
|
||
|
|
// Handle delete operation
|
||
|
|
const handleDelete = (index: number) => {
|
||
|
|
const newValues = inputValues.filter((_, i) => i !== index);
|
||
|
|
|
||
|
|
// Ensure at least one input remains
|
||
|
|
const finalValues = newValues.length === 0 ? [""] : newValues;
|
||
|
|
|
||
|
|
// Update internal state
|
||
|
|
setInputValues(finalValues);
|
||
|
|
|
||
|
|
// Call external onChange if provided
|
||
|
|
onChange?.(finalValues);
|
||
|
|
};
|
||
|
|
|
||
|
|
// Add new input field
|
||
|
|
const handleAdd = () => {
|
||
|
|
const newValues = [...inputValues, ""];
|
||
|
|
|
||
|
|
// Update internal state
|
||
|
|
setInputValues(newValues);
|
||
|
|
|
||
|
|
// Call external onChange if provided
|
||
|
|
onChange?.(newValues);
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="space-y-2">
|
||
|
|
{inputValues.map((item, index) => (
|
||
|
|
<div key={index} className="flex items-center space-x-2 group">
|
||
|
|
<Input
|
||
|
|
value={item}
|
||
|
|
onChange={(e) =>
|
||
|
|
handleInputChange(index, e.target.value)
|
||
|
|
}
|
||
|
|
placeholder={placeholder}
|
||
|
|
className="flex-grow"
|
||
|
|
/>
|
||
|
|
{inputValues.length > 1 && (
|
||
|
|
<Button
|
||
|
|
type="text"
|
||
|
|
icon={<DeleteOutlined />}
|
||
|
|
danger
|
||
|
|
className="opacity-0 group-hover:opacity-100"
|
||
|
|
onClick={() => handleDelete(index)}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
<div className="flex items-center space-x-2 group">
|
||
|
|
<Button
|
||
|
|
type="dashed"
|
||
|
|
block
|
||
|
|
onClick={handleAdd}
|
||
|
|
className="w-full">
|
||
|
|
添加输入框
|
||
|
|
</Button>
|
||
|
|
{inputValues.length > 1 && (
|
||
|
|
<Button
|
||
|
|
type="text"
|
||
|
|
icon={<DeleteOutlined />}
|
||
|
|
danger
|
||
|
|
className="opacity-0"
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default InputList;
|