@@ -7,6 +7,79 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
88## [ Unreleased]
99
10+ ## [ 1.11.0] — 2026-06-02
11+
12+ ### Added
13+ - ** Faithful rendering for every form-spec ` widget.kind ` (#664 ).** The
14+ form-spec wire declares 23 ` widget.kind ` values; the change form previously
15+ mapped only 5 and let the rest silently fall back to the control implied by
16+ ` FieldType ` — so ` hidden ` rendered as a * visible, editable* input,
17+ ` split-datetime ` collapsed to one control, and the multi-selects / ` file `
18+ had no faithful path. ` adaptFormSpec ` now maps ** all 23** explicitly (an
19+ exhaustive ` Record<WidgetKind, …> ` so a new kind is a compile error), and
20+ ` FieldInput ` gained branches for ` hidden ` (real hidden input),
21+ ` split-datetime ` (date + time), ` select-date ` (date input),
22+ ` checkbox-multiple ` / ` select-multiple ` (checkbox bank / ` <select multiple> ` ),
23+ ` autocomplete ` / ` autocomplete-multiple ` , and ` file ` (limited control + a
24+ legacy-admin note; upload itself still tracked by #241 ). Any future kind
25+ with no rich renderer maps to an explicit, operator-visible
26+ ` unsupported_widget ` tracked fallback — never a silent wrong control.
27+ ` adaptFormSpec.test.ts ` now asserts every enum member maps to something
28+ sensible.
29+ - ** System checks for misconfiguration (#667 ).** A new
30+ ` django_admin_react/checks.py ` registers a ` manage.py check ` validator that
31+ surfaces, with actionable hints: ` django_admin_rest_api ` missing from
32+ ` INSTALLED_APPS ` (Error), an unimportable ` ADMIN_SITE ` dotted path (Error),
33+ unknown ` DJANGO_ADMIN_REACT ` keys (Error, at startup instead of a lazy
34+ ` ValueError ` ), an ` API_URL_PREFIX ` that requires the consumer to mount the
35+ REST API themselves (Warning), and a missing built SPA bundle / Vite
36+ manifest (Warning).
37+
38+ ### Changed
39+ - ** ` list_display_links ` is now honoured (#666 ).** The changelist wire emits
40+ ` list_display_links ` (rest-api); the SPA links exactly the configured
41+ column(s) to the change page — and links * none* (rows inert) when the admin
42+ sets ` list_display_links = None ` . Previously the SPA hard-pinned the link to
43+ the first column. A pre-1.6.0 backend (no field on the wire) keeps the
44+ legacy first-column behaviour.
45+ - ** Raised the ` django-admin-rest-api ` floor to ` ^1.6.0 ` (#664 ).** 1.6.0 adds
46+ ` prepopulated_fields ` + autocomplete hints to the form-spec wire (already
47+ consumed for the add form via #245 /#629 ; the autocomplete hint now drives
48+ the ` autocomplete ` widget kind).
49+ - ** README parity table corrected (#668 ).** ` raw_id_fields ` , ` radio_fields ` ,
50+ and ` filter_horizontal ` / ` filter_vertical ` flip to ✅ (they ship today —
51+ pk-input + lookup, radio bank, and the ` ShuttleSelect ` two-pane widget).
52+ The stale "does NOT carry through" entries for those hooks were removed, and
53+ a new section documents the genuine gaps: ` empty_value_display ` (hard-coded
54+ ` — ` ), custom ` AdminSite.each_context ` extra keys, and ` list_select_related ` .
55+
56+ ### Security
57+ - ** Validated + sandboxed the legacy-admin iframe (#665 ).** ` legacy_url ` from
58+ the form-spec ` legacy-iframe ` fallback is now validated before it reaches
59+ the ` <iframe src> ` / ` <a href> ` sinks: only a same-origin ` http(s) ` URL is
60+ framed/linked; a ` javascript: ` / ` data: ` / ` blob: ` scheme or an off-origin
61+ target renders an inert error card instead (mirroring the
62+ ` action-redirect.ts ` discipline every other navigational sink in the SPA
63+ follows). The iframe now carries
64+ ` sandbox="allow-forms allow-scripts allow-same-origin" ` (defence in depth —
65+ drops ` allow-top-navigation ` / ` allow-popups ` / ` allow-modals ` ).
66+ ` SECURITY.md ` §QSEC-03 gained ` frame-src 'self' ` and documents the
67+ X-Frame-Options ↔ legacy-iframe interaction.
68+
69+ ### Performance
70+ - ** Route-level code-splitting + show-all row windowing (#670 ).** ` LoginPage `
71+ and ` CreatePage ` are now ` React.lazy ` -loaded at the route boundary (out of
72+ the first-paint main chunk). The "Show all N" (` ?all ` ) list path applies
73+ native row windowing (` content-visibility: auto ` ) so off-screen rows skip
74+ layout/paint while staying in the DOM for find-in-page / a11y.
75+
76+ ### Fixed
77+ - ** i18n: routed untranslated strings through ` t() ` (#669 ).** ` FieldInput ` 's
78+ ` Lookup ↗ ` / lookup aria-label, the ` — select — ` / ` (none) ` placeholders,
79+ and the time / array / range / FK placeholders, plus ` App.tsx ` 's "Page not
80+ found.", now go through the catalog; the new keys (and the #664 / #665
81+ operator notes) were added to the es / fr / pt catalogs.
82+
1083## [ 1.10.1] — 2026-06-02
1184
1285### Fixed
0 commit comments