import {Settings2} from 'lucide-react';
import {useState} from 'react';
import {Button} from '@/components/ui/button';
import {Checkbox} from '@/components/ui/checkbox';
import {Field, FieldDescription, FieldGroup, FieldLabel} from '@/components/ui/field';
import {Input} from '@/components/ui/input';
import {Popover, PopoverContent, PopoverTrigger} from '@/components/ui/popover';
import {ScrollArea} from '@/components/ui/scroll-area';
import {Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue} from '@/components/ui/select';
import {Separator} from '@/components/ui/separator';
import {Textarea} from '@/components/ui/textarea';
import type {WAFIPGroup, WAFRuleNode} from '@/lib/services/openflare';
const countries = ['CN', 'US', 'JP', 'SG', 'DE', 'FR', 'GB', 'CA', 'AU', 'BR', 'IN', 'KR'].map((value) => ({value, label: value}));
const regions = ['CN-BJ', 'CN-SH', 'CN-GD', 'CN-ZJ', 'US-CA', 'US-NY', 'US-TX', 'JP-13', 'DE-BE', 'GB-ENG'].map((value) => ({value, label: value}));
export function NodeProperties({node, ipGroups, onChange}: {node?: WAFRuleNode; ipGroups: WAFIPGroup[]; onChange: (node: WAFRuleNode) => void}) {
return ;
}
function PropertyFields({node, ipGroups, onChange}: {node: WAFRuleNode; ipGroups: WAFIPGroup[]; onChange: (node: WAFRuleNode) => void}) {
if (node.type === 'start' || node.type === 'allow') return
系统节点无需配置。
;
if (node.type === 'ip_match') return onChange({...node, config: {...node.config, ips}})}/> onChange({...node, config: {...node.config, cidrs}})}/> ({value: String(group.id), label: group.name}))} value={node.config.ip_group_ids.map(String)} onChange={(values) => onChange({...node, config: {...node.config, ip_group_ids: values.map(Number)}})}/>;
if (node.type === 'geo_match') return onChange({...node, config: {...node.config, countries}})}/> onChange({...node, config: {...node.config, regions}})}/>;
if (node.type === 'pow') return 算法{(['difficulty', 'session_ttl', 'challenge_ttl'] as const).map((key) => onChange({...node, config: {...node.config, [key]: value}})}/>)};
return onChange({...node, config: {...node.config, status_code}})}/>HTML 响应体;
}
function CsvField({id, label, value, onChange}: {id: string; label: string; value: string[]; onChange: (value: string[]) => void}) { return {label}; }
function NumberField({id, label, value, min, max, onChange}: {id: string; label: string; value: number; min?: number; max?: number; onChange: (value: number) => void}) { return {label} onChange(Number(event.target.value))}/>; }
function MultiSelect({id, label, options, value, creatablePattern, onChange}: {id: string; label: string; options: {value: string; label: string}[]; value: string[]; creatablePattern?: RegExp; onChange: (value: string[]) => void}) {
const [draft, setDraft] = useState('');
const normalized = draft.trim().toUpperCase();
const visible = [...options, ...value.filter((selected) => !options.some((option) => option.value === selected)).map((selected) => ({value: selected, label: selected}))];
const canCreate = Boolean(creatablePattern?.test(normalized) && !value.includes(normalized));
return {label}{creatablePattern && setDraft(event.target.value)}/>
}{visible.length === 0 ? 暂无可选项
: visible.map((option) => )};
}