"use client"; import { Plus, Trash2 } from "lucide-react"; import { useMemo, useState } from "react"; import { Badge, Button } from "@/components/ui"; import { cn } from "@/components/ui/cn"; import { Checkbox, Code, ErrorNote, Field, Input, Select, Textarea } from "../primitives"; import { toYaml } from "../yaml"; import { COMMON_FIELDS, configToRule, EXTRACT_KINDS, extractorToConfig, newFieldRule, RULE_TYPES, TRANSFORMS, type DevtoolShared, type FieldRule } from "./state"; export function StepRules({ s }: { s: DevtoolShared }) { const { draft, update } = s; const ex = draft.extractor; const [advanced, setAdvanced] = useState(false); const [jsonText, setJsonText] = useState(""); const [jsonError, setJsonError] = useState(null); const config = useMemo(() => extractorToConfig(ex, { includeMatch: true }), [ex]); const yamlPreview = useMemo(() => toYaml({ extractors: { [ex.name.trim() || ex.kind]: config } }), [config, ex.name, ex.kind]); const setEx = (patch: Partial) => update({ extractor: { ...ex, ...patch }, yamlDirty: draft.yamlDirty }); const setField = (id: string, patch: Partial) => setEx({ fields: ex.fields.map((f) => (f.id === id ? { ...f, ...patch } : f)) }); const suggestions = COMMON_FIELDS[ex.kind] ?? []; const usedNames = new Set(ex.fields.map((f) => f.name.trim()).filter(Boolean)); const duplicates = ex.fields.map((f) => f.name.trim()).filter((n, i, a) => n && a.indexOf(n) !== i); const openAdvanced = () => { setJsonText(JSON.stringify(config, null, 2)); setJsonError(null); setAdvanced(true); }; const applyAdvanced = () => { try { const o = JSON.parse(jsonText) as Record; const fields = Object.entries((o.fields ?? {}) as Record).map(([n, r]) => configToRule(n, r)); setEx({ kind: typeof o.kind === "string" ? o.kind : ex.kind, key: typeof o.key === "string" ? o.key : "", each: typeof o.each === "string" ? o.each : "", parser: typeof o.parser === "string" ? o.parser : "", minCertainty: o.minCertainty != null ? String(o.minCertainty) : "", match: Array.isArray(o.match) ? (o.match as string[]).join("\n") : ex.match, fields }); setAdvanced(false); setJsonError(null); } catch (e) { setJsonError((e as Error).message); } }; return (
setEx({ name: e.target.value.replace(/[^a-z0-9_-]/gi, "") })} mono placeholder="facility" /> setEx({ key: e.target.value })} mono placeholder="{url}" /> setEx({ each: e.target.value })} mono placeholder=".facility-card" /> setEx({ minCertainty: e.target.value })} mono placeholder="0.5" inputMode="decimal" />