import { Dispatch, SetStateAction, useState, useRef } from "react"; import { Input } from "@/components/ui/input"; import { Checkbox } from "@/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { StringMap } from "@/types/typeUtils"; import { Button } from "@/components/ui/button"; export class RegexSetting { placeholder: string; pattern: RegExp; constructor(placeholder: string, pattern: RegExp) { this.placeholder = placeholder; this.pattern = pattern; } } export type SettingsSchema = StringMap< "boolean" | "string" | "number" | string[] | RegexSetting >; export default function Settings({ settings, setSettings, schema, onSave, }: { settings: T; setSettings: Dispatch>; schema: SettingsSchema; onSave: () => void; }) { const [feedback, setFeedback] = useState< undefined | { kind: "error" | "info"; message: string } >(); // Ref to store debounce timer const debounceRef = useRef(undefined); const handleChange = (key: string, value: any) => { setSettings((prev) => ({ ...prev, [key]: value })); }; const handleRegexChange = ( key: string, regexSetting: RegexSetting, value: string ) => { handleChange(key, value); if (debounceRef.current) clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => { if (!regexSetting.pattern.test(value)) { setFeedback({ kind: "error", message: `Value does not match the pattern!`, }); } else { setFeedback(undefined); } }, 1500); }; const renderInput = (key: string, type: any) => { if (Array.isArray(type)) { return ( ); } else if (type === "boolean") { return ( handleChange(key, val)} /> ); } else if (type === "string") { return ( handleChange(key, e.target.value)} /> ); } else if (type === "number") { return ( handleChange(key, Number(e.target.value))} /> ); } else if (type instanceof RegexSetting) { return ( handleRegexChange(key, type, e.target.value)} /> ); } }; return ( <> {Object.entries(schema).map(([key, type]) => (
{renderInput(key, type)}
))} {feedback && (
{feedback.message}
)} ); }