Skip to content

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog.

Versions follow CalVer: YY.Quarter.Build β€” e.g. 26.2.1 = year 2026, quarter 2, build 1. Beta releases append .beta (e.g. 26.2.1.beta); production releases have no suffix.

[26.4.5] β€” 2026-11-01

Forms can now respond to what's entered and show answers back: conditional fields, field groups and grid widths in one model, read-only review pages, and text and consent blocks between fields. There are no breaking changes for apps using the public API.

✨ Added

  • Field(ui_group="Contact") puts fields under a titled section without nesting the data, and a group can be its own tab, accordion panel or wizard step. ui_cols=6 (1-12) sets a field's width so consecutive fields share a row. ui_group_collapsible, ui_group_collapsed and ui_group_show_when apply to a whole group. (#241)
  • Field(ui_show_when={"field": "contact", "equals": "phone"}) hides a field until another field has a given value, with in, truthy and not_empty as well. A hidden field submits nothing and isn't validated, and "required": True makes a field required only while it shows. It works inside sub-forms and model_list items, and display mode leaves hidden fields out. (#237)
  • FormModel.render_display(data, framework=..., layout=..., edit_urls=...) shows validated data read-only, as a review or confirmation page, with the form's labels, order and sections. Selects show their label, booleans Yes or No, and model_list a table. Passwords are masked, card and social security numbers show only their last four digits, and content blocks are left out. (#238)
  • Field(ui_element="content", ui_content=...) puts text between fields. It submits nothing and is left out of validation and the returned data. (#274)
  • Field(ui_element="consent", ui_content=...) pairs text with a checkbox, with ui_options={"scrollable": True} for long text. (#274)

πŸ—‘οΈ Removed

  • The internal FRAMEWORKS dict, get_framework_config() and the renderer's config attribute. Each style's classes now live on its theme, and rendered output is unchanged. (#281)

πŸ› Fixed

  • Bootstrap select, multiselect, combobox, radio and checkbox group fields no longer render a second mb-3 wrapper. Spacing is unchanged. (#280)

[26.4.4] β€” 2026-10-31

The Material style is rebuilt on Material Design 3 and shares one rendering path with Bootstrap and plain HTML. A checkbox can now be required with Literal[True]. This is a breaking release for apps that customize Material forms.

πŸ’₯ Breaking Changes

  • framework="material" is rewritten on Material Design 3 and now renders through the same path as Bootstrap and plain. Every input gets a Material field: outlined with a floating label and a real notch, with error, disabled and icon states. The CSS uses design tokens (--md-sys-color-*) and has no !important. CSS written against the old Material markup needs updating. (#265)
  • MaterialEmbeddedTheme is renamed MaterialTheme. Update any import or subclass of it. (#265)

πŸ”„ Changed

  • Star rating stars are now buttons in every style, in a radiogroup with arrow-key support, so the widget works from the keyboard. The default colors are darker, to meet contrast requirements. (#265)

✨ Added

  • Field(unchecked_message="...") sets the error shown when a required checkbox is left unticked. (#273)
  • Radio variant="segmented" and checkbox group variant="button_group" now ship their own CSS instead of leaving it to the app. (#265)
  • docs/advanced/material.md documents the Material style. (#265)
  • material_variant="filled" selects filled text fields (the default is "outlined"). (#265)
  • Opt-in dark mode for Bootstrap forms: under data-bs-theme="dark" the library's widgets, tabs, accordion and wizard now follow Bootstrap's dark colors. (#265)
  • --sf-* CSS tokens re-color those same parts under Bootstrap. (#265)
  • Opt-in dark scheme for Material: data-md-theme="dark" on the form or an ancestor, or the page's color-scheme. (#265)

πŸ› Fixed

  • A checkbox typed Literal[True] can now pass validation: ticking it used to fail with "Input should be True". This is the way to require a box to be ticked, such as accepting terms. (#273)
  • Material forms now submit to the server and show every error at once, like Bootstrap. They used to drop novalidate, so the browser stopped a single-page form at its first invalid field. (#265)
  • A model list item's title no longer goes through innerHTML as the user types, so markup in a title field can't run in the page. (#265)
  • Material: invalid fields now get a red outline, and textareas, radios, multiselects, comboboxes and data tables are no longer unstyled. (#265)

πŸ—‘οΈ Removed

  • Materialize is no longer vendored or referenced. The Material style has long used its own self-contained theme and never loaded Materialize, but the package still shipped Materialize 1.0.0 (about 320 KB), a vendor-update-materialize make target, and a Materialize config behind framework_css_tag/framework_js_tag. They're gone: both functions now return nothing for "material", and get_theme_for_framework("material") returns the Material theme the renderer actually uses. (#265)

[26.4.3] β€” 2026-10-29

FormModel is now the only way to build a form: the builder API, the prebuilt forms, @form_validator and the React/Vue adapters are removed. Five Agent Skills ship inside the package, and a long list of form bugs is fixed. This is a breaking release; see docs/upgrading.md.

πŸ’₯ Breaking Changes

  • React and Vue adapters removed. ReactJSONSchemaFormAdapter, VueFormulateAdapter, and their modules (integration.json_schema_form_adapter, integration.vue_formulate_adapter, and the integration.react/integration.vue shims) are deleted, along with the React/Vue-only helpers map_ui_element_to_framework and convert_validation_rules. They produced config blobs for client-side form libraries, outside this library's server-rendered scope, and had no examples or docs. For a JSON Schema of a form, use FormModel.get_json_schema(); for a plain Pydantic model, use FormModel.as_api_model(). (#248)
  • The builder API is removed; FormModel is the only way to build a form. FormBuilder, AutoFormBuilder, create_form_from_model, create_login_form, create_registration_form, create_contact_form, render_form_page, FormIntegration, handle_form and handle_form_async are deleted, along with ModernFormRenderer, FormDefinition and FormSection (which only existed to render builder forms) and the integration.builder/adapters/sync/async_support modules. The builder rendered through its own path, so it never got layout=, the wizard, nested sub-forms, model_list or DataTableLayout. To upgrade: declare a FormModel (or build one at runtime with Pydantic's create_model(..., __base__=FormModel)), render it with render_form_html() and handle submissions with FormModel.validate() and result.render_with_errors(). See docs/upgrading.md. Importing any removed name raises an ImportError that names its replacement. (#255)
  • @form_validator is removed. It never ran: nothing called the methods it decorated, so cross-field checks written with it were silently skipped. Use Pydantic's @model_validator(mode="after") (its message lands in the form-wide _errors) or FormValidator.add_cross_field_rule. (#254)
  • DataTableLayout input names are namespaced by the embedding field. Cells, the CSV file input and the Load/Submit buttons used to have fixed names (rows[i].col, csv_file, datatable_action), so two tables on one page overwrote each other. They are now named under the field the table is embedded in (an employees field submits employees.rows[i].col, employees.csv_file, employees.datatable_action), and the default table id comes from the field name instead of the row model's class name. handle_import_post() and parse_submitted_rows() find their table in the submission themselves, so app code using them doesn't change. Code that reads those form keys directly, or builds test submissions by hand, must use the new names. When two tables share a row model, pass the new field= argument to say which one to read. (#253)

✨ Added

  • Agent Skills ship inside the package. uvx library-skills --claude installs five skills into an app project, linked to the installed version: pydantic-schemaforms (build and fix forms, with references for inputs, complex forms, validation, data tables, security, rendering and extending), schemaforms-create (a new form from a description such as "create a login form", commented like a tutorial), schemaforms-convert (from Pydantic, dataclasses, JSON Schema, WTForms or Django), schemaforms-upgrade (from removed APIs) and schemaforms-document (docstrings, help text and a Markdown page for an app's forms). The single-file instructions from get_app_instructions() and the CLI are now built from the same sources, and their examples come from tested files. (#264)
  • Accessibility gate. The Playwright suite runs axe-core 4.14 against WCAG 2.0, 2.1 and 2.2 A and AA rules plus axe best practices on every example page under Bootstrap and Material, plus the validation page's error state, and fails on any serious or critical violation. axe-core is vendored for tests only (tests/playwright/vendor/, pinned by version and SHA-256); it is not shipped in the package. What is tested, the baseline the inputs meet, and what automated testing does not cover are in the new docs/reference/accessibility.md page and the README. This is testing, not a claim of ADA, Section 508 or WCAG conformance. (#246)

πŸ› Fixed

  • Two tabbed or accordion forms on one page no longer collide. Tab and accordion ids were numbered from tab-0/accordion-0 in every form, so the second form's tabs and panels controlled the first form's. Each layout now gets its own id prefix, and tab and accordion scripts only act inside their own layout (which also stops an outer tab hiding a nested tabbed sub-form). (#252)
  • Accordion fixes: under Bootstrap the open section rendered closed, and under plain HTML and Material clicking a section header submitted the form. (#252)
  • Invalid fields are announced. After a failed submit, a field's control gets aria-invalid="true" and an aria-describedby pointing at its error message, and at its help text whenever it has one, under Bootstrap, Material and plain HTML. Help and error elements now carry matching <id>-help / <id>-error ids. (#246)
  • DataTableLayout cells have accessible names. Each editable cell gets an aria-label such as "Email, row 3", since its column header is not a <label>. (#246)
  • The tags input's label names its text box. The visible text box now takes the field's id, so <label for=...> points at it, and it receives the aria-* wiring above. (#246)
  • The code editor's highlight layer no longer takes keyboard focus. It is aria-hidden, but Prism made it tabbable. (#246)
  • Contrast meets WCAG AA (4.5:1) for tag chips, the code editor's property/tag syntax color and the "Rendered in" timing line. (#246)
  • The date picker toggle is a 24Γ—24 px target (WCAG 2.2 target size). (#246)
  • Inputs are inferred from more field types. Without a ui_element, date, datetime, time, EmailStr and AnyUrl fields render as date, datetime-local, time, email and URL inputs; Enum and Literal fields render as a select with their values; and a list of either renders as a multiselect. Optional fields keep their input type instead of falling back to a text box. Previously an Enum field rendered an empty section (or a select with no options), so its choices had to be built by hand. (#258)
  • A fresh form shows the model's defaults. When no form_data is passed, every field starts at its default (an int = 1 shows 1, an Enum or Literal default is selected, a bool = True checkbox is ticked, default_factory values included). Passed data, such as a submission being re-rendered or an edit form, is still used as is. Previously defaults were never rendered, so they had to be passed in form_data by hand. (#258)
  • Validator messages are shown as written. A ValueError raised in a @field_validator or @model_validator shows its own message, without Pydantic's "Value error, " prefix. (#258)
  • Optional selects can be left empty. An Optional select gets an empty first choice, and submitting it validates to None, including for str-based enums. (#258)
  • An Enum field keeps its title when it matches the Enum class's name (Field(title="Size") on a Size enum), including inside list items; it used to fall back to the field name. (#258)
  • Material renders datetime fields as datetime-local, not the invalid datetime input type. (#258)
  • Pre-filling an Enum field selects its option. form_data holding an Enum member, as a database row or model_dump() does, used to leave the select (or radio) with nothing chosen. (#258)
  • A checkbox that defaults to True can be unticked. An unticked checkbox sends nothing, so validate() used to fill in the default and return True. In a form submission, a missing checkbox that has a default is now False; one without a default is still required, and nested JSON that omits it still gets the default. (#258)
  • An optional sub-form (Address | None) can be left empty. Its inputs are no longer required, and when every one of them is blank or still at its default, validate() returns None for it instead of field errors. (#258)
  • A currency input works on a Decimal, float or int field. The input formats what is typed as $1,234.50, which used to fail validation as "Input should be a valid decimal". In a form submission the symbol and thousands separators are now stripped first. (#258)
  • A float field accepts decimals in the browser. Number inputs always had step="1", so the browser refused 39.50. A float field now gets step="any", and multiple_of sets the step. (#258)
  • Material inputs carry the field's constraints. min_length, max_length, ge, le and pattern now become minlength, maxlength, min, max and pattern attributes under Material too, as they already did under Bootstrap and plain HTML. (#258)
  • MinLengthRule skips an empty value, like every other rule except RequiredRule and like its own client-side check. It used to reject "", so an optional field with a minimum length couldn't be left blank. (#258)

[26.4.1] β€” 2026-10-12

Complex forms are now built one way: nest FormModels as fields of a parent FormModel and pick a layout=. Data in and out is nested JSON. This is a breaking release; see docs/upgrading.md.

πŸ’₯ Breaking Changes

  • Form-orchestration classes removed. TabbedLayout, ListLayout, SectionDesign, FormDesign, FormLayoutBase, and the form_layouts VerticalLayout/HorizontalLayout wrappers now raise FormLayoutRemovedError (a TypeError) when subclassed or called. The message contains the upgrade steps and points to the new "Upgrading to nested forms" section of the AI instructions.
  • Top-level VerticalLayout/HorizontalLayout now name the flex layout primitives from rendering/layout_engine.py, which the removed wrappers used to shadow.
  • pydantic_schemaforms.layouts (the deprecated re-export shim) is deleted.
  • FormModel.validate(flatten=...) removed. result.data is always nested like the model. Passing flatten raises a TypeError explaining this.
  • ValidationResult.errors is a nested error tree shaped like the data (errors["pets"][1]["name"]) instead of string-path keys (errors["pets[1].name"]). Container and form-wide messages use the reserved "_errors" key instead of "general".
  • layout="tabbed"/"side-by-side" group sub-forms. The field-name keyword heuristic and the two-fields-per-row pairing are gone; on a form with no sub-form fields these layouts raise ValueError. Several input_type="layout" fields no longer auto-render as tabs; pass layout="tabbed".
  • Unknown layout= values raise ValueError instead of rendering vertically.
  • Non-validation exceptions propagate from validate() instead of being shown on the form as errors["general"].
  • Renderer internals: RenderContext.all_errors is replaced by child_errors (the field's own error sub-tree), and render_field() takes the field's error node as error with no all_errors argument. get_nested_form_data, EnhancedFormRenderer._humanize_error_field, and FieldRenderer.extract_nested_errors_for_field are removed.
  • handle_form/handle_form_async with a model return nested data and a nested error tree. FormValidator.validate_pydantic_model() (which kept only the first segment of each error path) is removed.

✨ Added

  • Sub-form fields. A field typed as another FormModel (or Optional of one) renders as a titled section with inputs named address.city, with no ui_element needed. ui_collapsible/ui_collapsed render it as a <details> section that opens when it holds an error.
  • Grouped layouts: layout="tabbed", "side-by-side", and the new "accordion" arrange the parent's plain fields plus one group per sub-form, in declaration order (ui_order overrides). Re-rendering after a failed submit opens the first group that contains an error.
  • Step wizard: layout="wizard" shows the same groups one step at a time with a progress header and Back/Next. All steps are in one <form>, so one POST submits everything. Next runs the browser's validation on the current step; a re-render opens the first step with an error and marks the others. Options: wizard_options={"linear", "show_progress", "back_label", "next_label"} and Field(ui_step_title=...). Without JavaScript all steps show stacked.
  • Examples cover every layout, input, and validation, enforced by tests/test_examples_coverage.py and a browser test that loads every example page: the widget gallery shows every input type and alias with each of its options plus field-level options (ui_disabled, ui_readonly, icon, ...); /validation shows every Pydantic constraint, validator, rule class, and a cross-field rule failing on one form; /layouts takes the wizard options as query parameters; /employees/directory shows the read-only DataTableLayout options.
  • validate() takes the raw request form (Starlette FormData, Werkzeug MultiDict, (name, value) pairs) as well as nested dicts, keeping repeated values as lists. render_form_html(form_data=...) accepts the same.
  • render_with_errors(errors=...) re-renders with a different error tree, e.g. the result's own errors merged with a rule-based FormValidator's.
  • AI instructions now list every ui_options key per widget with its default, every field-level option, the rule classes and cross-field rules, the FormModel/ValidationResult API, every render option, and the asset helpers.
  • ValidationResult.error_list() (flat [{"loc": [...], "msg": ...}]) and ValidationResult.instance (the validated model).
  • list[FormModel] fields render as repeating sub-forms without ui_element="model_list".
  • LiveValidator.register_model_validator() registers sub-form and list-item fields under their input names (address.city, pets[].name).
  • validate_form_data is exported from the top-level package, as the validation guide already documented.
  • docs/complex_forms.md, a guide to composing forms and upgrading.

πŸ› Fixed

  • Decoding a submission compacts list indices instead of padding gaps with None: pets[0] and pets[2] decode to a two-item list, so an item removed without re-indexing still validates, and one field named like pets[500000000].name no longer makes the server allocate a list that long.
  • validation_response_headers, wrap_with_schemaforms_markers, read_asset_text, bootstrap_icons_css_content and bootstrap_icons_css_tag are exported from the top-level package; the docs and examples imported them from internal modules.
  • Removing every item of a repeating sub-form now fails its min_length instead of passing as the field's default (form submissions only; nested JSON that omits the key still gets the default).
  • Under layout="tabbed"/"accordion"/"wizard", Material forms no longer let the browser block submission on a required input in a hidden group with no visible message; the server re-renders with that group open.
  • A layout field's default_factory that raises is no longer silently swallowed (the table rendered empty); the error propagates.
  • radio and checkbox_group never showed the current value: a re-rendered form lost the user's choices. A combobox lost its value the same way.
  • A field declared ui_element="hidden" rendered a visible label (only ui_hidden=True produced a bare hidden input).
  • Custom date_format/time_format/datetime_format were not applied to ISO string values (JSON data), which showed as 2024-06-15 instead of the format.
  • The file input's preview script failed to parse (a # comment in JavaScript), so no preview appeared; it now shows file names as text, never as markup.
  • Material: the colour picker's hex readout (show_value) was missing, and a select with a placeholder had its label overlapping the placeholder text.
  • Switching tabs left the active class on the first panel.
  • Field(icon=...), like other non-Pydantic keywords, was silently dropped when any ui_* option was also passed.
  • Material forms' inline script failed to parse (a # comment in JavaScript), so its floating-label and field enhancements never ran.
  • Field() silently dropped any ui_* option it doesn't name as a parameter (such as ui_collapsible) when another ui_* option like ui_help_text was also passed. All ui_* options are now kept.
  • Validation errors now reach fields inside sub-forms and are namespaced per sub-form, so two sub-forms with the same field name no longer collide.
  • Library code no longer imports from the examples/ package or hard-codes the demo app's field names.
  • DataTableLayout.parse_submitted_rows() no longer turns cell values like "1" or "yes" into booleans before validation.
  • The documented FormConfig/TabbedLayout((...)) and HorizontalLayout(label_cols=...) recipes, which never worked, are replaced.
  • Several documentation examples that interpolated submitted values into HTML with f-strings now use html(t"...").

[26.2.3] β€” 2026-06-28

πŸ› Fixed

  • LiveValidator.register_model_validator partial-validation bug β€” previously called model_class.model_validate({field: value}) with only one field's data; if the model had other required fields, Pydantic raised ValidationError for them, causing all unrelated fields to produce is_valid=False with no errors even when the value was valid. Now uses __pydantic_validator__.validate_assignment(model_construct(), field_name, value) to validate each field in isolation, independent of sibling required fields.

  • LiveValidator.render_field_with_live_validation single-trigger limitation β€” the if/elif/elif chain for validate_on_blur / validate_on_input / validate_on_change silently dropped every trigger after the first truthy one. Changed to independent if checks so all enabled triggers combine into a single hx-trigger attribute (e.g. hx-trigger="blur, change" when both are True).

✨ Added

  • Live-validation example β€” GET /live-validation demo route in the FastAPI example app shows a contact form with per-field HTMX validation on blur. Includes POST /validate/{field_name} HTMX endpoint using validation_response_headers() and GET /vendor/htmx.min.js to serve the vendored HTMX asset.

[26.2.2] β€” 2026-06-28

✨ Added

  • FormModel.as_api_model() β€” new class method that returns a pure Pydantic BaseModel with ui_* rendering metadata stripped from json_schema_extra. Allows the same model class to serve both as an HTML form and as a typed FastAPI body / response_model without ui_element, ui_placeholder, etc. appearing in the OpenAPI/Swagger docs. Field(title=...), Field(examples=[...]), descriptions, and all validation constraints (min_length, ge, pattern, …) are fully preserved. Result is cached per subclass and safe to assign at module level (ContactSchema = ContactForm.as_api_model()).

πŸ”„ Changed

  • Reduced SonarCloud code smells: extracted duplicate magic strings to named constants, prefixed unused parameters with _, renamed methods that shadowed class attributes, and merged nested if statements into compound conditions across multiple modules.

[26.2.1] β€” 2026-05-17

First production release. All public Quick Start code paths verified working end-to-end.

πŸ’₯ Breaking Changes

  • submit_url is now explicit across public form render APIs and no longer defaults silently. Calls that omit submit_url raise a clear ValueError, enforcing app-owned routing boundaries.

✨ Added

  • HTMX live validation β€” LiveValidator, HTMXValidationConfig, and validation_response_headers() provide server-side field validation triggered by blur/input events via HTMX without page reloads.
  • Branch coverage β€” branch = true added to coverage configuration for deeper test quality.
  • HTML structural validation β€” tests/test_html_structural.py validates tag balance across all frameworks and field types.
  • HTTP integration tests β€” FastAPI TestClient and Flask test_client round-trip tests.
  • Property-based tests β€” Hypothesis suite covering arbitrary field names, labels, and frameworks.
  • Performance benchmarks β€” pytest-benchmark suite for small, medium, and large form rendering.
  • Playwright browser tests β€” End-to-end HTMX validation tests against a live FastAPI server (tests/playwright/), running in CI on Chromium.
  • macOS in CI matrix β€” Tests now run on ubuntu-latest, windows-latest, and macos-latest.
  • py.typed marker for PEP 561 compatibility.
  • Vendored assets (htmx, Bootstrap, Materialize, iMask) with sha256 manifest verification.
  • .gitattributes forcing LF line endings on vendored assets for cross-platform checksum stability.

πŸ› Fixed

  • create_form_from_model crashed with any Pydantic model β€” AutoFormBuilder._build_from_model used the wrong parameter name (default_value instead of value) and compared against ... instead of PydanticUndefined; the sentinel leaked into json_schema_extra, causing PydanticSerializationError on every render call.
  • Windows path separator in test assertion caused CI failure on win32.
  • Dependabot config used unsupported interval: "cron" β€” silently ignored, causing weekly runs. Replaced with interval: "monthly".
  • HTMX live validation JS used JSON.parse(responseText) on HTML responses; replaced with the idiomatic HX-Trigger: validationResult header pattern so CSS classes are applied correctly.
  • except A, B: tuple syntax preserved via # fmt: skip to prevent ruff from removing parentheses that pyright requires.

πŸ”„ Changed

  • Layout rendering internals refactored for maintainability and reduced cognitive complexity.
  • Reliability and maintainability improvements to satisfy SonarCloud quality gate.
  • Improved nested/collapsible form behavior when multiple forms are rendered on a page.
  • Pre-commit ruff version pinned to match requirements.txt to eliminate local/CI formatting drift.
  • Pyright added to make tests so type errors surface before commit.

⬆️ Dependencies

  • fastapi[all]: 0.121.2 β†’ 0.128.4
  • ruff: 0.14.14 β†’ 0.15.0
  • tqdm: 4.67.1 β†’ 4.67.3
  • pytest-html: 4.1.1 β†’ 4.2.0
  • packaging: 25.0 β†’ 26.0
  • black: 25.12.0 β†’ 26.1.0
  • mkdocstrings[python]: 1.0.0 β†’ 1.0.1
  • pymdown-extensions: 10.20 β†’ 10.20.1

Latest Changes

πŸš€ Production Releases

πŸš€ 26.4.2 Β· Support for Python 3.15

πŸ“… Published 2026 October 24, 21:09

🎁 Changes

πŸ“ Documentation

  • Documentation: Clarify Python Requirement, Asset Modes, Examples, and Testing Workflow (#234) (@devsetgo)
  • Documentation: Remove Stale 26.4.1 Release-Notes Draft From Repo Root (#232) (@devsetgo)

πŸ”§ Maintenance

  • Chore: Bump Version To 26.4.2 For Python 3.15 Support (#233) (@devsetgo)
  • Documentation: Remove Stale 26.4.1 Release-Notes Draft From Repo Root (#232) (@devsetgo)

πŸ™Œ Contributors

@devsetgo

πŸš€ 26.3.7 Β· Enhancement: Collapse and Select Improvements

πŸ“… Published 2026 August 29, 22:05

🎁 Changes

  • Update project dependencies and configurations (#219) (@devsetgo)

✨ Features

  • Add collapsible option groups and menu order example for checkboxes/radios (#221) (@devsetgo)
  • Add optional forced-selection placeholder to select dropdowns (#220) (@devsetgo)

πŸ› Bug Fixes

  • Expand and improve AI assistant app-building instructions (#218) (@devsetgo)

πŸ“ Documentation

πŸ”§ Maintenance

πŸ™Œ Contributors

@devsetgo and @claude

πŸš€ 26.3.6 Β· Browser Cache Bug

πŸ“… Published 2026 August 23, 21:17

🎁 Changes

πŸ› Bug Fixes

  • Reset CSV import page to blank state on each new visit (#216) (@devsetgo)

πŸ“ Documentation

  • Reset CSV import page to blank state on each new visit (#216) (@devsetgo)

πŸ”§ Maintenance

  • Reset CSV import page to blank state on each new visit (#216) (@devsetgo)

πŸ™Œ Contributors

@devsetgo and @claude

πŸš€ 26.3.5 Β· Bug Fix: CSV Import

πŸ“… Published 2026 August 23, 20:54

🎁 Changes

πŸ› Bug Fixes

  • Fix DataTableLayout to submit all pages during large data imports (#215) (@devsetgo)

πŸ“ Documentation

  • Fix DataTableLayout to submit all pages during large data imports (#215) (@devsetgo)

πŸ”§ Maintenance

  • Fix DataTableLayout to submit all pages during large data imports (#215) (@devsetgo)

πŸ™Œ Contributors

@devsetgo and @claude

πŸš€ 26.3.4 Β· Enhancement: CSV Import

πŸ“… Published 2026 August 23, 19:08

🎁 Changes

πŸ“ Documentation

  • Deep documentation pass across library, examples, and docs (#213) (@devsetgo)
  • Add DataTableLayout composite control for CSV import to table (#212) (@devsetgo)
  • Demo Application and MonoRepo (#207) (@devsetgo)

πŸ”§ Maintenance

πŸ™Œ Contributors

@devsetgo and @claude

πŸš€ 26.3.3 Β· Enhancements to JSON output and new input types

πŸ“… Published 2026 August 07, 21:33

🎁 Changes

✨ Features

  • Fix register_input_class registry and expand AI-assistant instructions (#202) (@devsetgo)

πŸ“ Documentation

πŸ‘· GitHub Actions

πŸ”§ Maintenance

πŸ™Œ Contributors

@devsetgo, @dependabot[bot] and @claude

πŸš€ 26.3.2 Β· New Input Types and Bug Fixes

πŸ“… Published 2026 July 19, 18:46

🎁 Changes

πŸ› Bug Fixes

  • Feature: Fix ui_element registry collisions; expand AI assistant docs with a verified example (#180) (@devsetgo)

πŸ“ Documentation

  • Dev (#183) (@devsetgo)
  • Add Tier-2 input widgets and Widget Gallery example, fix Material bugs (#181) (@devsetgo)
  • Feature: Fix ui_element registry collisions; expand AI assistant docs with a verified example (#180) (@devsetgo)

πŸ‘· GitHub Actions

  • github-actions(deps): bump SonarSource/sonarqube-scan-action from 8.1.0 to 8.2.0 (#172) (@dependabot[bot])
  • github-actions(deps): bump actions/checkout from 5 to 7 (#169) (@dependabot[bot])
  • github-actions(deps): bump release-drafter/release-drafter from 7.3.1 to 7.5.1 (#170) (@dependabot[bot])

πŸ”§ Maintenance

πŸ™Œ Contributors

@dependabot[bot], @devsetgo and dependabot[bot]

πŸš€ 26.3.1 Β· America 250 Release: Adding AI Help Instructions and Clean Up.

πŸ“… Published 2026 July 03, 23:12

🎁 Changes

Happy 250th Birthday USA!!!!

✨ Features

πŸ› Bug Fixes

πŸ“ Documentation

πŸ‘· GitHub Actions

πŸ”§ Maintenance

πŸ™Œ Contributors

@devsetgo

πŸš€ 26.2.4 Β· Live Validation Fix, Example, and Doc Updates

πŸ“… Published 2026 June 28, 14:32

🎁 Changes

✨ Features

πŸ› Bug Fixes

πŸ“ Documentation

πŸ”§ Maintenance

πŸ™Œ Contributors

@devsetgo

πŸš€ 26.2.1.beta Β· CSRF Feature Release

πŸ“… Published 2026 April 26, 19:26

🎁 Changes

✨ Features

πŸ”§ Maintenance

πŸ™Œ Contributors

@dependabot[bot], @devsetgo and dependabot[bot]

πŸš€ 26.1.8.beta Β· Removing External Validation Logic

πŸ“… Published 2026 February 27, 21:32

🎁 Changes

πŸ› Bug Fixes

  • Removing validation logic outside of library. (#71) (@devsetgo)

πŸ™Œ Contributors

@devsetgo

πŸš€ 26.1.7.beta Β· Bug fix and cleanup.

πŸ“… Published 2026 February 22, 19:56

🎁 Changes

πŸ› Bug Fixes

  • fix(layouts): validate nested layout submissions and restore Preferen… (#70) (@devsetgo)

πŸ™Œ Contributors

@devsetgo

πŸš€ 26.1.6.beta Β· Many fixes, enhancements, and increasing code coverage

πŸ“… Published 2026 February 22, 16:35

🎁 Changes

✨ Features

πŸ› Bug Fixes

πŸ”§ Maintenance

πŸ™Œ Contributors

@dependabot[bot], @devsetgo and dependabot[bot]

πŸš€ 26.1.2.beta Β· Bug fixes and Improvements

πŸ“… Published 2026 January 09, 21:46

🎁 Changes

✨ Features

πŸ› Bug Fixes

πŸ”§ Maintenance

πŸ™Œ Contributors

@dependabot[bot], @devsetgo and dependabot[bot]

πŸ§ͺ Pre-releases

πŸ§ͺ 26.1.1.beta Β· Initial Beta Release

πŸ“… Published 2026 January 02, 19:13

🎁 Changes

✨ Features

πŸ› Bug Fixes

πŸ”§ Maintenance

πŸ™Œ Contributors

@devsetgo