You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(spa): editable Range fields — two-input editor wired to the [lower, upper] write shape (#242) (#538)
Closes **#242**. The backend already serializes ranges as the
`{subtype, value: {lower, upper, bounds}}` envelope (#141) and now
accepts `[lower, upper]` on the write path (#533) — this PR pairs that
with the SPA-side editor, matching the JSON / Duration / Array editors
that already shipped.
- @dar/api `contract.ts`: add the previously-missing `'range'` to
`FieldType` so the closed vocabulary matches what the backend has been
emitting (it's documented in `docs/api-contract.md` §field types; the
TS mirror was stale). No wire change.
- @dar/form `FieldInput`: a `range` branch renders two text inputs
(lower / upper) bound to the `[lower, upper]` write shape
`_range_endpoints` accepts. An empty side = unbounded. Subtype-aware
formatting is the user's job — Django's `MultiValueField` sub-fields
validate each side and surface a bad value as a normal field error,
same contract as the JSON / Duration / Array editors.
- Seeders unwrap the read envelope into the `[lower, upper]` pair in
the three sites that prepare form state: `CreatePage`, `DetailPage`'s
`initialValueFor`, and `RelatedAddModal`'s `seedValue`. Empty / missing
envelopes seed to `['', '']` so new objects start with two blank
inputs instead of an unsupported shape.
Tests: two new `FieldInput` cases — non-empty value renders both inputs
and emits `[newLower, oldUpper]` / `[oldLower, newUpper]` independently;
a `null` value renders two empty inputs. Full vitest **142 passed**;
typecheck + ESLint (--max-warnings 0) + stylelint + dark-mode guard
clean; `pnpm build` ok.
Closes#242
Co-authored-by: Martin Castro Laminrs <mcastro@laminr.ai>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments