import { ReactNode, useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@ui/card"; import { StringConfig } from "./components/string"; import { ArrayConfig } from "./components/array"; import { BooleanConfig } from "./components/boolean"; import { NumberConfig } from "./components/number"; import { Button } from "@ui/button"; import { Tabs, TabsList } from "@ui/tabs"; import { TabsContent, TabsTrigger } from "@radix-ui/react-tabs"; export type ConfigSetter = ( update: (curr: Partial) => Partial ) => void; export type OverideFn, P extends keyof T> = ( value: T[P], set: ConfigSetter ) => ReactNode; export type Overides> = { [P in keyof T]?: | OverideFn | Overides ? T[P] : never>; }; type DeepDisabled> = { [P in keyof T]?: | boolean | DeepDisabled ? T[P] : never>; }; type DeepDescription> = { [P in keyof T]?: T[P] extends Record ? DeepDescription : string; }; type ArrayDefaults> = { [P in keyof T]?: T[P] extends unknown[] ? T[P][number] : never; }; function findDeepDisabled>( field: string, disabled?: boolean | DeepDisabled ) { if (disabled === undefined) { return false; } if (typeof disabled === "boolean") { return disabled; } else { return disabled[field]; } } export function Config>({ config, update, set, overrides, descriptions, arrayDefaults, disabled, }: { config: T; update: Partial; set: ConfigSetter; overrides?: Overides; descriptions?: DeepDescription; arrayDefaults?: ArrayDefaults; disabled?: boolean | DeepDisabled; }) { const config_keys = Object.keys(config); const [show, setShow] = useState(config_keys[0]); return (
{Object.keys(config).map((config) => ( ))}
{Object.entries(config).map(([field, value]) => { if (show !== field) return null; const val = update[field] ?? value; const overide = overrides?.[field]; if (overide && typeof overide === "function") { return overide(update[field] ?? (value as T[string]), (updt) => set((curr) => ({ ...curr, [field]: updt( update[field] ?? (config[field] as Partial) ), })) ) as ReactNode; } if (typeof val === "string") { return ( set((curr) => ({ ...curr, [field]: u(val), })) } description={descriptions?.[field] as string | undefined} disabled={findDeepDisabled(field, disabled) as boolean} /> ); } if (typeof val === "boolean") { return ( set((curr) => ({ ...curr, [field]: u(val) }))} description={descriptions?.[field] as string | undefined} disabled={findDeepDisabled(field, disabled) as boolean} /> ); } if (typeof val === "number") { return ( set((curr) => ({ ...curr, [field]: u(val) }))} description={descriptions?.[field] as string | undefined} disabled={findDeepDisabled(field, disabled) as boolean} /> ); } if (Array.isArray(value)) { const val = (update[field] ? update[field] : value) as unknown[]; return ( ); } return ( {field.replaceAll("_", " ")} } update={update[field] ?? {}} set={(update) => { set((curr) => ({ ...curr, [field]: update( curr[field] ?? (config[field] as Partial) ), })); }} overrides={ overrides?.[field] as Overides> } disabled={findDeepDisabled(field, disabled)} /> ); })}
); }