diff --git a/src/features/run/ConfigForm.tsx b/src/features/run/ConfigForm.tsx index 3f3259b89..34c9f94bc 100644 --- a/src/features/run/ConfigForm.tsx +++ b/src/features/run/ConfigForm.tsx @@ -3,12 +3,29 @@ * common ones, the options added through "Modify options" (⌥M) and the * Before launch list. */ -import { useRef, useState, type ReactNode } from "react"; +import { useMemo, useRef, useState, type KeyboardEvent, type ReactNode, type RefObject } from "react"; import clsx from "clsx"; import type { BeforeLaunchTask, RunConfig } from "@/platform/ipc"; import { useWorkflowSettings } from "@/platform/workflowSettings"; import { useTx, useTxTemplate } from "@/platform/i18n"; -import { Button, Checkbox, Icon, IconButton, Input, Menu, Select, T, type MenuItem, type SelectOption } from "@/ui"; +import { + Button, + Checkbox, + HighlightedText, + Icon, + IconButton, + Input, + List, + listNavigate, + Menu, + Popup, + SearchField, + Select, + T, + fuzzyMatch, + type MenuItem, + type SelectOption, +} from "@/ui"; import { useContributions, type RunConfigTypeContribution } from "@/workbench/contributions"; import { TASK_LABELS, taskLabel, type BeforeLaunchKind } from "./beforeLaunch"; import { @@ -712,6 +729,26 @@ function OutputField({ label, text }: { label: string; text: string }) { ); } +/** Candidate rows for a compound's member picker: every config except itself and ones already added. */ +export function memberRows( + config: RunConfig, + all: readonly RunConfig[], + members: readonly string[], + query: string, +): Array<{ config: RunConfig; indices: number[] | null }> { + const q = query.trim(); + return all + .filter( + (c) => + c.id !== config.id && + !members.includes(c.id) && + !compoundCycle({ ...config, compound: [...members, c.id] }, all), + ) + .map((c) => ({ c, indices: q ? fuzzyMatch(c.name, q) : null })) + .filter((x) => !q || x.indices) + .map(({ c, indices }) => ({ config: c, indices })); +} + function CompoundMembers({ config, all, @@ -725,10 +762,9 @@ function CompoundMembers({ }) { const tx = useTx(); const members = config.compound ?? []; - const candidates = all.filter( - (c) => - c.id !== config.id && !members.includes(c.id) && !compoundCycle({ ...config, compound: [...members, c.id] }, all), - ); + const addRef = useRef(null); + const [addOpen, setAddOpen] = useState(false); + const hasCandidates = memberRows(config, all, members, "").length > 0; return (
@@ -748,19 +784,131 @@ function CompoundMembers({
); })} -