feat(ui): form-level onChange with per-input debounce (#2151)#2265
Merged
Conversation
c07c6ea to
176b2bb
Compare
…2151 Runtime helper for form-level onChange with per-input debounce support. Listens to input events via delegation, reads data-vertz-debounce from targets, coalesces via microtask batching, cancels pending timers on immediate flush. Includes full test coverage (17 tests). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…2151 - Transform debounce={N} to data-vertz-debounce on input/textarea/select - Transform <form onChange={handler}> to __formOnChange(el, handler) - Register __formOnChange in import injection system - 12 new JS-side compiler tests covering all transform cases Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add FormHTMLAttributes with onChange?: (values: FormValues) => void - Add InputHTMLAttributes, TextareaHTMLAttributes, SelectHTMLAttributes with debounce?: number - Update IntrinsicElements with specific types for form/input/textarea/select - Forward debounce prop as data-vertz-debounce in ComposedInput and ComposedTextarea - Type-level tests verify correct and incorrect usage Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- E2E acceptance test covering search/filter pattern, rapid typing, mixed interactions, form.reset(), cleanup, and type safety - Document form-level onChange, per-input debounce, limitations, escape hatch, and form() interaction in forms guide - Add changeset for @vertz/ui, @vertz/ui-primitives, @vertz/native-compiler Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add disposed flag to prevent handler fire after cleanup (B1) - Guard parseInt against NaN with || 0 fallback (S4) - Add test for cleanup-during-pending-flush race condition (S2) - Improve comments for FormValues cast and reset timing (S1, S3) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ross-test leak The CSS injection tests relied on resetInjectedStyles() to clean up, but orphaned sheets from other test files remained in document.adoptedStyleSheets. Clear adoptedStyleSheets directly in beforeEach/afterEach for reliable isolation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rm onChange #2151 Document the debounce prop on Input and Textarea in the component library guide, and add a cross-reference to form-level onChange in the form API reference page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
176b2bb to
be79cf8
Compare
This was referenced Apr 4, 2026
This was referenced Apr 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
<form onChange={handler}>that fires with all form values (FormValuesobject) when any child input changesdebounce={ms}prop on<input>,<textarea>,<select>to control per-input callback timingonChangeon<form>to__formOnChange(el, handler)anddebounce={N}todata-vertz-debounce="N"Closes #2151
Public API Changes
Breaking
onChangeon<form>now receivesFormValuesinstead of a DOMEvent. Useref+addEventListenerfor the raw DOM event.Additions
packages/ui/src/dom/form-on-change.ts—__formOnChangeruntime helper (compiler target)packages/ui/src/jsx-runtime/index.ts—FormHTMLAttributes,InputHTMLAttributes,TextareaHTMLAttributes,SelectHTMLAttributesJSX typesFormValuestype exported from@vertz/uidebounce?: numberprop on Input/Textarea theme componentsCompiler
native/vertz-compiler-core/src/jsx_transformer.rs—debounce→data-vertz-debouncerename on form elements,onChangeon<form>→__formOnChangenative/vertz-compiler-core/src/import_injection.rs—__formOnChangeauto-importPhases
__formOnChangewith microtask batching, per-input debounce viadata-vertz-debounce, disposal scope cleanup (18 tests)debounceprop rename andform onChangerouting (12 new compiler tests, 81 total)Review Findings
Adversarial review found 1 blocker (flush-after-disposal race condition) — fixed by adding
disposedflag inflush(). 6 should-fix items addressed (NaN guard, test coverage, comments).Test plan
__formOnChangeruntime helper passFormValueshandler anddebounce: numberpackages/ui🤖 Generated with Claude Code