Skip to content

chore(dev): release 4.0.0 - #220

Merged
phmatray merged 1 commit into
devfrom
release-please--branches--dev--components--formcraft
Sep 25, 2026
Merged

phmatray merged 1 commit into
devfrom
release-please--branches--dev--components--formcraft

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor

🤖 I have created a release beep boop

4.0.0 (2026-09-24)

⚠ BREAKING CHANGES

  • lov: ILovConfiguration<TItem, TValue> gained a GetByKeyProvider property. A custom class implementing that interface must add it (returning null keeps the previous behaviour). Configurations built through LovBuilder are unaffected.
  • lov: MudBlazorLovFieldComponent and FluentUILovFieldComponent gained a TKey type parameter (<TModel, TValue, TKey, TItem>), with TValue now the field's bound type. Code that renders these components directly by their old three-argument generic shape must add the key type; fields configured through .AsLov(...) / .AsMultiSelectLov(...) are unaffected.
  • lov: AsMultiSelectLov<TModel, TValue, TItem>'s configure parameter changed from Action<LovBuilder<TModel, IEnumerable<TValue>, TItem>> to Action<LovBuilder<TModel, TValue, TItem>>, so WithKey now takes the scalar item key. Callers with an explicitly-typed configure lambda must update the type; inferred lambdas are unaffected.
  • core: IFormConfiguration<TModel>.ShowValidationSummary now defaults to false (it was true, but had no effect). A form now renders a validation summary only after opting in with .ShowValidationSummary(). IFormConfiguration<TModel>.ShowRequiredIndicator, .RequiredIndicator, FormBuilder<TModel>.ShowRequiredIndicator(bool, string) and FormLayout.Horizontal are [Obsolete]. A consumer that builds with warnings as errors gets CS0618 until it moves to .WithNativeRequired() / FormLayout.Grid or suppresses the warning locally.
  • core: a nested field's FieldName is now its full dotted path (Shipping.Value), not its last member name (Value). This is visible through GetRequiredFields, OnFieldChanged, validation message keys (FieldIdentifier), DependsOn/group membership keys, and DOM ids built from the field name. Single-level fields are unchanged.
  • security: EncryptField now fails closed. An expression that does not resolve to a string property, or a path that cannot be resolved, throws ArgumentException at configuration time instead of being silently skipped. Nested members (x => x.Address.City) are now actually encrypted and stored under their full dotted path.
  • core: FormDiagnosticScope and DiagnosticLog moved from FormCraft.ForMudBlazor to FormCraft.Diagnostics (core). Code that references them by the old namespace must update its using directive. No forwarding shim is provided.
  • core: move the UI-agnostic adapter machinery into core (#279) (refactor(core)!: move the UI-agnostic adapter machinery into core (#279) #289)
  • core: expose Validators as IReadOnlyList and require AddValidator (#245)
  • lov: WithDisplay(Expression<Func<TItem,string>>) is removed. Pass a lambda directly, or expr.Compile() if you hold an Expression.

Features

  • core: localize default validation messages (#354) (#361) (6a9a2dc)
  • demo: redesign the demo site around code beside the live form (#390) (60766d3)
  • demo: redesign the demo site around the code-to-form binding (#268) (679e0a2)
  • fluentui: add a FormCraft.ForFluentUI adapter for Fluent UI Blazor v5 (#260) (#261) (713e358)
  • fluentui: bring the Fluent UI adapter to parity with MudBlazor (#278) (#291) (6f6acaf)
  • mudblazor: add a typed builder method for the native required opt-in (#204) (#236) (4210be4)
  • mudblazor: add a typed WithMask builder for text field masks (#265) (#273) (61e6445)
  • mudblazor: announce required fields without the HTML5 required attribute (#263) (#353) (3341705)
  • mudblazor: announce required file-upload fields to assistive technology (#262) (#270) (ba02aad)
  • mudblazor: give numeric adornments a typed click handler (#215) (#244) (8a03598)
  • mudblazor: make ShrinkLabel configurable per field and per form (#177) (#178) (7a7dc30)
  • mudblazor: warn when a mask blanks a stored value (#266) (#274) (1ea5425)
  • mudblazor: warn when ShrinkLabel=false cannot be honoured (#181) (#183) (b22d05d)
  • mudblazor: warn when the password toggle displaces a configured adornment (#219) (#243) (eccbf2d)

Bug Fixes

  • adapters: custom template no longer renders nothing for a non-property field (#330) (#387) (0d378af)
  • adapters: make Add/Remove inert and diagnosable on an unreadable collection binding (#433) (#439) (a8adaf5)
  • adapters: stop a null-intermediate collection binding from crashing render (#419) (#427) (1bd2dc3)
  • adapters: warn once on an unwritable nested collection item edit (#450) (#451) (e774a46)
  • adapters: write back through the field's compiled expression for custom templates (#413) (20d80c3)
  • build: stop Clean deleting the build output it is running from (#310) (#368) (7e3f9e7)
  • core: build CollectionSetter from the full nested member chain (#420) (#424) (9bac0ce)
  • core: evaluate DisabledCondition on render, mirroring VisibleWhen (#476) (#479) (e51c9ef)
  • core: honour or retire the inert form-level settings (#457) (8d75085)
  • core: keep collection validation messages consistent with the rendered form (#342) (#379) (69b56c4)
  • core: qualify collection field identity by its full nested path (#428) (#434) (e87756f)
  • core: qualify scalar field identity by its full nested path (#437) (37cb742)
  • core: resolve DisabledCondition in the core stub field renderers (#483) (#489) (f9df972)
  • core: share one security pipeline across both adapters (#321) (#402) (e1488a1)
  • core: stamp identifiers a validation pass writes fresh (#445) (#446) (a7e74ec)
  • core: stamp valid collection cells and skip hidden fields on write (#447) (#452) (430c664)
  • core: stop an unreadable nested binding from crashing render or validation (#397) (#403) (45d7c0d)
  • core: stop an unreadable nested collection binding from crashing validation (#414) (f52faa0)
  • core: stop FieldValueGetterCache swallowing genuine accessor faults and cancellation (#425) (#438) (6f6aaee)
  • core: validate each collection item field once per pass (#329) (#331) (65944e5)
  • demo: allow pinch-zoom in the Fluent UI demo (#341) (#360) (af2900e)
  • demo: correct ARIA state, disposal and fade-in regressions (#285) (#295) (3dd997c)
  • demo: guard every timed re-render against component disposal (#315) (#323) (8557ce3)
  • demo: make every demo page readable and fill the gallery (#405) (e5260fc)
  • demo: stop nesting cards in the form panel and give wide forms room (#411) (36e18c3)
  • fluentui: bind numeric bounds explicitly so a dropped bound is dropped (#348) (#382) (d4952cd)
  • fluentui: clear TooManyFilesError on a multiple-file-upload config swap (#416) (#421) (bd46189)
  • fluentui: focus the collection controls' own buttons, not their wrapper spans (#383) (#399) (f073d88)
  • fluentui: keep keyboard focus after collection controls unmount (#337) (#377) (59ea837)
  • fluentui: key collection rows on a weak per-item token (#401) (#410) (c73d088)
  • fluentui: re-read a field's configuration when the rendered field changes (#335) (#336) (d3af1ff)
  • lov: bind AsMultiSelectLov's WithKey to the scalar per-item key (#467) (70fa17c)
  • lov: let WithDisplay and WithKey accept a plain lambda (#180) (#182) (fa88097)
  • lov: resolve multi-select LOV component TValue from the field's bound type (#480) (0780e08)
  • lov: WithDataSource(collection) honors search/sort/context filters (#472) (a8f0561)
  • mudblazor: announce required fields to assistive technology (#199) (#254) (e8e3586)
  • mudblazor: bind a configured mask on both render paths (#211) (#253) (8484dba)
  • mudblazor: bind DisabledWhen to MudBlazor file upload components (#487) (0343e59)
  • mudblazor: bind factory masks whose pattern is computed lazily (#317) (#366) (75ebb81)
  • mudblazor: clear a multiple-file upload to an empty list, notifying once (#319) (#376) (0828678)
  • mudblazor: closing one LOV chip removes only that item instead of clearing the whole selection (#475) (0780e08)
  • mudblazor: dedupe field diagnostics across component re-mounts (#304) (#309) (44d46ff)
  • mudblazor: drop the write-only _valueLookup cache from the autocomplete component (#404) (#415) (769ec49)
  • mudblazor: focus Browse after clearing a file upload (#281) (#292) (da7d1dc)
  • mudblazor: forward a configured adornment to date item fields (#217) (#248) (b4b649f)
  • mudblazor: hide the upload's native file input and keep drops working (#456) (6d0de99)
  • mudblazor: honour a configured Culture on numeric item fields (#218) (#247) (e31a7e6)
  • mudblazor: honour Format and ShowSpinButtons on numeric fields (#208) (#240) (cefa8a8)
  • mudblazor: invoke the adornment click handler passed to WithAdornment (#192) (#194) (92add18)
  • mudblazor: judge the ShrinkLabel diagnostic on the rendered adornment (#212) (#241) (36dc2aa)
  • mudblazor: keep a password field masked when it also configures multiple lines (#207) (#232) (aea3e40)
  • mudblazor: key collection rows on a per-item weak token (#334) (#400) (705a48b)
  • mudblazor: map number, date and time to their input types (#210) (#239) (6dcab2d)
  • mudblazor: mask password fields inside collection item forms (#189) (#196) (421eee3)
  • mudblazor: move focus deliberately after a self-unmounting control (#318) (#324) (33102ff)
  • mudblazor: qualify the ShrinkLabel diagnostic key so scopes cannot collide (#242) (2d591c3)
  • mudblazor: re-read a field's configuration when the rendered field changes (#298) (#308) (947a3a5)
  • mudblazor: render a handler-less adornment as a plain icon, not a button (#216) (#224) (789acae)
  • mudblazor: render adornments on collection item fields (#184) (#188) (89f0dbc)
  • mudblazor: render adornments on numeric fields (#191) (#195) (7b3743f)
  • mudblazor: render each uploaded file once (#338) (#362) (e79abe4)
  • mudblazor: render long, float, short and byte collection item fields (#209) (#246) (0c8be25)
  • mudblazor: render novalidate on the form instead of applying it by script (#206) (#235) (c9b5047)
  • mudblazor: report post-init and partially-discarded masked values (#283) (#293) (af5c605)
  • mudblazor: stop emitting the HTML5 Required attribute on collection item fields (#190) (#193) (3bb3bde)
  • sanitize FieldName for CSS-safe DOM ids on nested fields (#449) (#453) (a47834f)
  • security: encrypt nested EncryptField members through their full path (#423) (5b9e5b3)
  • security: key audit log entries by full nested path, not last member (#406) (#412) (2e4fcf8)
  • security: redact nested audit keys by full path or last segment (#417) (#418) (bfc24df)
  • security: resolve EncryptField paths through inherited interface properties (#429) (#432) (864a071)
  • upload: resolve constraints through one path in every upload component (#340) (#388) (c1606a0)
  • validation: keep prior messages intact when ValidateModelAsync throws mid-pass (#440) (#441) (26ae1ff)
  • validation: stop message-store races in DynamicFormValidator (#443) (#444) (6052839)

Performance

  • core: compile each field's value getter once (#269) (#286) (cdc9ec4)
  • core: compile each field's value getter once per validation (#312) (#320) (320d689)
  • core: remove per-render reflection from the field render path (#314) (#378) (1cae68e)

Refactor

  • build: give the results directory one definition (#339) (#359) (3556327)
  • core: call the collection validator through a typed surface (#344) (#381) (bd725ba)
  • core: expose Validators as IReadOnlyList and require AddValidator (#245) (376866b)
  • core: move the UI-agnostic adapter machinery into core (#279) (#289) (e31cc39)
  • core: share collection row identity tracking across adapters (#422) (#442) (7b5111c)
  • core: share diagnostics warning log and per-form latch across adapters (#398) (c0044cf)
  • core: share numeric type-default resolution between both adapters (#389) (#393) (aaa27e9)
  • mudblazor: express the two diagnostic idioms once each (#284) (#294) (17e0dea)
  • mudblazor: render collection item fields through IFieldRendererService (#203) (#250) (5c66e29)

This PR was generated with Release Please. See documentation.

@phmatray

Copy link
Copy Markdown
Owner

🛑 Held deliberately — do not merge yet.

The 4.0.0 is correct: it comes from the BREAKING CHANGE footer on fa88097 (#180/#182 removed the WithDisplay(Expression<Func<TItem,string>>) overload), which landed after v3.1.0. The changelog scope is right too — it compares from v3.1.0 and lists only post-v3.1.0 work, so there was no whole-history fallback.

The decision is to ship 4.0.0 later, once a significant new feature and further bug fixes have landed. Until then this PR stays open and release-please keeps refreshing it on every push to dev. Nothing needs doing to hold it.

Two notes for whoever picks this up:

  1. The version will not drift upward. 4.0.0 already claims the major; additional feat: and fix: commits are absorbed into the same release and just extend the notes.
  2. Before merging, repoint the nuget.org Trusted Publishing policies. Both FormCraft and FormCraft.ForMudBlazor still name continuous.yml; they must name release-please.yml. Miss it and the merge produces a tag, a changelog and a GitHub Release — and no packages. (Tracked as part of Prove NuGet Trusted Publishing end-to-end and retire the long-lived NUGET_API_KEY #198.)

"No checks" on this PR is expected, not a gap. release-please opens it with GITHUB_TOKEN, and GitHub does not fire workflow runs for events created by that token — the same rule that forced publishing into release-please.yml in the first place. The build and full test suite run in the nupkg job against the tag, before anything is pushed to nuget.org.

@github-actions
github-actions Bot force-pushed the release-please--branches--dev--components--formcraft branch 2 times, most recently from 34a384b to 26e9e75 Compare August 11, 2026 22:32
@github-actions
github-actions Bot force-pushed the release-please--branches--dev--components--formcraft branch 25 times, most recently from 7cc560d to 92535ba Compare August 13, 2026 12:02
@github-actions
github-actions Bot force-pushed the release-please--branches--dev--components--formcraft branch 25 times, most recently from 0cf1b95 to 9670a28 Compare September 23, 2026 23:38
@github-actions
github-actions Bot force-pushed the release-please--branches--dev--components--formcraft branch 2 times, most recently from cd94e87 to b380c8b Compare September 23, 2026 23:54
@github-actions

Copy link
Copy Markdown
Contributor Author

🤖 Created releases:

🌻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant