Summary
Add field.linkedPair(label) — a composite that wraps two related sub-fields with a built-in linkage rule (e.g. password + confirm, or country + region cascade). Removes the repetitive cross-validation noise that today lives in every schema.
Why this would help
- Password confirmation, region cascading from country, "current value vs new value" change forms, "from / to" semantic pairs.
- Keeps the linkage rule next to the fields it relates to instead of scattered across validators.
- The two sub-fields keep their own typed APIs, so nothing breaks reusability.
Proposed API
field.linkedPair('Password')
.pair(
field.password('Password').required().strong(),
field.password('Confirm').sameAs('password'),
);
field.linkedPair('Location')
.cascade(
field.country('Country'),
field.select('Region').optionsFrom((country) => loadRegionsFor(country)),
);
Suggested implementation areas
src/core/field-descriptors/linked-pair/LinkedPairFieldBuilder.ts (new)
src/core/field-descriptors/field.ts
- generic linkage protocol:
pair(a, b) adds cross-validation, cascade(parent, child) adds child option re-derivation on parent change
src/renderers/web/ and src/renderers/native/ — render the two sub-fields stacked / inline depending on layout option
Acceptance Criteria
Summary
Add
field.linkedPair(label)— a composite that wraps two related sub-fields with a built-in linkage rule (e.g. password + confirm, or country + region cascade). Removes the repetitive cross-validation noise that today lives in every schema.Why this would help
Proposed API
Suggested implementation areas
src/core/field-descriptors/linked-pair/LinkedPairFieldBuilder.ts(new)src/core/field-descriptors/field.tspair(a, b)adds cross-validation,cascade(parent, child)adds child option re-derivation on parent changesrc/renderers/web/andsrc/renderers/native/— render the two sub-fields stacked / inline depending on layout optionAcceptance Criteria
pair()runs the linkage validator on every change of either sub-fieldcascade()re-derives the child's options when the parent value changespassword.value,password.confirm) — final shape is documentedpair()andcascade()with realistic schemas (password sameAs, country/region)