Fix double node creation when picking a palette entry by click

- TextField: new onSubmit callback (Enter only, independent of value change)
- NodePalette: use onSubmit instead of onChange, add per-open picked guard
- e2e: new check 13a (type + click row -> exactly one node), wait for
  Chromium exit in finally with SIGKILL escalation after 5s

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Fable 5.1 committed 2026-09-07 13:03:10 +02:00
1 parent 922774778b
commit 06b1007015
3 files changed
+48 -4

No files matched your search

+11 -1
View File
@@ -12,6 +12,12 @@ export interface TextFieldOptions {
onInput?: (value: string) => void;
/** Fires on Enter / blur when the value changed since editing started. */
onChange?: (value: string) => void;
/**
* Fires on Enter only (before the blur commit), regardless of whether the value changed.
* Use this for "accept" semantics (search boxes, dialogs) instead of `onChange`, which
* also fires when focus is taken away by a click elsewhere.
*/
onSubmit?: (value: string) => void;
}
/**
@@ -39,6 +45,7 @@ export class TextField extends Widget implements TextEditTarget {
placeholder: string;
onInput?: (value: string) => void;
onChange?: (value: string) => void;
onSubmit?: (value: string) => void;
constructor(value = '', options: TextFieldOptions = {}) {
super();
@@ -46,6 +53,7 @@ export class TextField extends Widget implements TextEditTarget {
this.placeholder = options.placeholder ?? '';
this.onInput = options.onInput;
this.onChange = options.onChange;
this.onSubmit = options.onSubmit;
this.focusable = true;
this.cursor = 'text';
this.minHeight = Theme.controlHeight;
@@ -174,7 +182,9 @@ export class TextField extends Widget implements TextEditTarget {
onBridgeKey(event: KeyboardEvent): boolean {
if (event.key === 'Enter') {
ui().focus.blur(); // triggers onBlur → commit
this.onSubmit?.(this.valueText);
// onSubmit may have closed/destroyed us; only blur if we are still the focused widget.
if (ui().focus.focused === this) ui().focus.blur(); // triggers onBlur → commit
return true;
}
if (event.key === 'Escape') {