fix(flows): allow multiple comma-separated keywords in trigger (#234)

The list-view keyword trigger input parsed its value into the keywords
array on every keystroke (split/trim/filter(Boolean)) and re-rendered
from keywords.join(", "). Typing a comma produced a trailing empty
segment that filter(Boolean) dropped, so the comma was stripped the
instant it was typed — making it impossible to enter a second keyword.

Extract a KeywordsInput component that holds a local draft string and
only commits (parse + dedupe-empties + rejoin) on blur / Enter, mirroring
the automations builder's KeywordMatchConfig. Multi-keyword entry like
"support, help, hi" now works.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Arnas Donauskas 2026-06-11 11:16:16 +03:00
parent c3f8b3f71d
commit 82caecec09
No known key found for this signature in database

View File

@ -202,6 +202,55 @@ export function FlowBuilder() {
} }
// ============================================================
// Keyword trigger input
// ============================================================
/**
* Comma-separated keyword entry. Keeps a local draft string so the
* comma (and trailing space) the user types survive until they're done
* — parsing into the keywords array on every keystroke stripped the
* trailing comma the instant it was typed, making it impossible to
* start a second keyword (issue #234). We commit on blur / Enter, then
* re-display the cleaned, rejoined form. Seeded once on mount; the
* component unmounts/remounts when the trigger type changes, so the
* seed stays in sync. Mirrors the automations builder's KeywordMatchConfig.
*/
function KeywordsInput({
keywords,
onChange,
}: {
keywords: string[];
onChange: (keywords: string[]) => void;
}) {
const [draft, setDraft] = useState(keywords.join(", "));
function commit() {
const parsed = draft
.split(",")
.map((k) => k.trim())
.filter(Boolean);
setDraft(parsed.join(", "));
onChange(parsed);
}
return (
<Input
value={draft}
onChange={(e) => setDraft(e.target.value)}
onBlur={commit}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
commit();
}
}}
placeholder="support, help, hi"
className="bg-slate-800"
/>
);
}
// ============================================================ // ============================================================
// Trigger panel // Trigger panel
// ============================================================ // ============================================================
@ -253,26 +302,18 @@ function TriggerPanel({
<label className="mb-1 block text-xs text-slate-400"> <label className="mb-1 block text-xs text-slate-400">
Keywords (comma-separated) Keywords (comma-separated)
</label> </label>
<Input <KeywordsInput
value={ keywords={
Array.isArray(state.trigger_config.keywords) Array.isArray(state.trigger_config.keywords)
? (state.trigger_config.keywords as string[]).join(", ") ? (state.trigger_config.keywords as string[])
: "" : []
} }
onChange={(e) => onChange={(keywords) =>
setState((s) => ({ setState((s) => ({
...s, ...s,
trigger_config: { trigger_config: { ...s.trigger_config, keywords },
...s.trigger_config,
keywords: e.target.value
.split(",")
.map((k) => k.trim())
.filter(Boolean),
},
})) }))
} }
placeholder="support, help, hi"
className="bg-slate-800"
/> />
</div> </div>
)} )}