+
+
+
+
+
+
+ {ACTION_TYPES.map((a) => (
+
+ {a}
+
+ ))}
+
+
+
+
+ {step.action === "pause" && (
+
+ {
+ const v = parseInt(e.target.value, 10);
+ updateStepField("ms", isNaN(v) ? undefined : v);
+ }}
+ />
+
+ )}
+
+ {(step.action === "click" ||
+ step.action === "hover" ||
+ step.action === "wait" ||
+ step.action === "scroll" ||
+ step.action === "moveTo" ||
+ step.action === "select") && (
+ <>
+
+ updateStepField("selector", e.target.value)}
+ />
+
+
+ updateStepField("text", e.target.value)}
+ />
+
+
+ updateStepField("within", e.target.value)}
+ />
+
+ >
+ )}
+
+ {step.action === "click" && (
+
+
Modifiers
+
+ {MODIFIERS.map((mod) => (
+
+ toggleModifier(mod, !!v)}
+ />
+ {mod}
+
+ ))}
+
+
+ )}
+
+ {step.action === "select" && (
+
+ updateStepField("value", e.target.value)}
+ />
+
+ )}
+
+ {step.action === "type" && (
+ <>
+
+ updateStepField("text", e.target.value)}
+ />
+
+
+ updateStepField("selector", e.target.value)}
+ />
+
+
+ updateStepField("within", e.target.value)}
+ />
+
+
+ {
+ const v = parseInt(e.target.value, 10);
+ updateStepField("charDelay", isNaN(v) ? undefined : v);
+ }}
+ />
+
+ >
+ )}
+
+ {step.action === "key" && (
+ <>
+
+ updateStepField("key", e.target.value)}
+ />
+
+
+ )?.selector as string) ?? "")
+ }
+ placeholder="CSS selector (optional)"
+ onChange={(e) => updateStepField("target", e.target.value || undefined)}
+ />
+
+ >
+ )}
+
+ {step.action === "navigate" && (
+
+ updateStepField("url", e.target.value)}
+ />
+
+ )}
+
+ {step.action === "screenshot" && (
+
+ updateStepField("output", e.target.value)}
+ />
+
+ )}
+
+ {step.action === "scroll" && (
+ <>
+
+ {
+ const v = parseInt(e.target.value, 10);
+ updateStepField("x", isNaN(v) ? undefined : v);
+ }}
+ />
+
+
+ {
+ const v = parseInt(e.target.value, 10);
+ updateStepField("y", isNaN(v) ? undefined : v);
+ }}
+ />
+
+ >
+ )}
+
+ {step.action === "wait" && (
+
+ {
+ const v = parseInt(e.target.value, 10);
+ updateStepField("timeout", isNaN(v) ? undefined : v);
+ }}
+ />
+
+ )}
+
+ {step.action === "drag" && (
+ <>
+
+
+ From
+
+
+
+
+ To
+
+
+ >
+ )}
+
+ {step.action !== "pause" && (
+ <>
+
+
+ {
+ const v = parseInt(e.target.value, 10);
+ updateStepField("delay", isNaN(v) ? undefined : v);
+ }}
+ />
+
+ >
+ )}
+
+
+ updateStepField("label", e.target.value)}
+ />
+
+
+ updateStepField("description", e.target.value)}
+ />
+
+
+ );
+}
+
+// ─── Props Pane ─────────────────────────────────────────────────────────────
+
+const ACTIONS_WITH_SELECTOR = new Set([
+ "click",
+ "hover",
+ "wait",
+ "scroll",
+ "moveTo",
+ "select",
+ "type",
+]);
+
+export function PropsPane() {
+ const selectedVideo = useAtomValue(selectedVideoAtom);
+ const videoConfig = useAtomValue(selectedVideoConfigAtom);
+ const selectedStep = useAtomValue(selectedStepIndexAtom);
+ const [configJson] = useAtom(configJsonAtom);
+ const { config } = useAtomValue(parsedConfigAtom);
+ const [pickedSelector, setPickedSelector] = useAtom(pickedSelectorAtom);
+ const commit = useSetAtom(commitConfigAtom);
+ const step =
+ videoConfig && selectedStep >= 0 ? videoConfig.steps[selectedStep] : undefined;
+
+ const prevPickedRef = useRef