/** * Step 2 — Branch shape: count, depth, scenes-per-branch. * * The wizard fetches `/health` once and passes the limits in via * props so the inputs hard-cap to whatever the backend allows. * The estimated total node count is recomputed live so users see * "≈18 nodes" before they ever press Create. */ import React, { useMemo } from "react"; import { AlertTriangle } from "lucide-react"; import type { WizardForm } from "../wizardState"; export interface Step2Props { form: WizardForm; setForm: (patch: Partial) => void; limits: { max_branches: number; max_depth: number; max_nodes_per_experience: number }; } export function Step2Branches({ form, setForm, limits }: Step2Props) { const estimatedNodes = useMemo( () => form.branch_count * form.depth * Math.max(1, form.scenes_per_branch), [form.branch_count, form.depth, form.scenes_per_branch], ); const overCap = estimatedNodes > limits.max_nodes_per_experience; return (
setForm({ branch_count: v })} /> setForm({ depth: v })} /> setForm({ scenes_per_branch: v })} />
{overCap && }
Upper-bound estimate: ≈{estimatedNodes} nodes {" "}(choices × steps × scenes; the merge collapser usually trims this).
{overCap && (
Exceeds the configured cap of {limits.max_nodes_per_experience}. Reduce choices, steps, or video length — or the planner will cap it for you.
)}
); } function NumberField({ label, hint, value, min, max, onChange, }: { label: string; hint?: string; value: number; min: number; max: number; onChange: (v: number) => void; }) { const id = `ix_${label.replace(/\s+/g, "_").toLowerCase()}`; return (
{hint &&

{hint}

}
onChange(parseInt(e.target.value, 10) || min)} className="flex-1 accent-[#3ea6ff]" aria-valuemin={min} aria-valuemax={max} aria-valuenow={value} /> onChange(clamp(parseInt(e.target.value, 10) || min, min, max))} className="w-20 bg-[#121212] border border-[#3f3f3f] rounded-md px-2 py-1.5 text-sm text-center outline-none focus:border-[#3ea6ff]" /> / {max} max
); } function clamp(n: number, lo: number, hi: number): number { if (n < lo) return lo; if (n > hi) return hi; return n; } /** Always valid — caps are enforced by the input components. */ export function step2Valid(_f: WizardForm): boolean { return true; }