Changelog

View Source

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

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Planned

  • i18n support via GetText
  • Field-level permissions
  • Conditional field rendering
  • Multi-step form wizards
  • Form draft auto-save

[0.4.0] - 2026-05-01

This release is a substantial reshape of the public API. The DSL now supports one form per Ash action (the v0.3 single-form model is gone), themes are pluggable by short atom name, mix tasks were renamed to match Phoenix conventions, and the default UI for booleans and many-to-many is friendlier out of the box. The default theme also ships with a from-scratch iOS-style wheel datepicker, an upsert-aware multiselect combobox, and a first-class :file_upload DSL.

๐Ÿ’ฅ Breaking changes

  • Multi-form DSL. A resource's form do โ€ฆ end block is replaced by a forms do form :action do โ€ฆ end end section. Each form :action entity declares its own submit label, fields, nested blocks, theme, accent, and transition style. Multiple form blocks per resource now work correctly (the old form do โ€ฆ end syntax silently merged them into one โ€” see #1).

  • AshFormBuilder.Info accessors take an action. Every accessor (form_fields/2, form_nested/2, form_submit_label/2, etc.) now takes the action atom as its second argument. New helpers: forms/1, form_config/2, form_theme/2, form_accent/2, form_transitions/2. The old 1-arity form_action/1 is removed โ€” use forms/1 and inspect config.action.

  • Resource.Form helper module reshape. The transformer now generates for_create/1, for_read/1, for_update/2, for_destroy/2, plus a generic for_action/2. Introspection helpers nested_forms/1, schema/1, and required_preloads/1 are now action-keyed; actions/0 lists declared actions. The old nested_config/0 and action/0 are removed.

  • Mix tasks renamed and reshaped.

    • mix ash_form_builder.gen.live Context Resource โ†’ mix ash_form.gen.live -r MyApp.Context.Resource
    • mix ash_form_builder.gen.form MyApp.Resource โ†’ mix ash_form.gen.form -r MyApp.Resource

    Both tasks now require --resource / -r and accept --theme, --accent, --transitions flags.

  • Default boolean UI is now :toggle (animated switch). Set type :checkbox in the DSL to opt back into a square checkbox.

  • Default many-to-many UI is now :checkbox_group (vertical list of checkboxes). Set type :multiselect_combobox for the searchable multi-select.

โœจ Added

  • iOS-style wheel datepicker in AshFormBuilder.Themes.Default. Triggered as a centered modal <dialog> with three (date) or five (datetime) scroll-snap wheels for month / day / year (+ hour / minute). Day wheel auto-clamps to month length (Feb 29, 30-day months). Pure Tailwind + scroll-snap CSS + a single colocated hook โ€” no JS deps. Smooth scroll feel via scroll-behavior: smooth, scroll-snap-stop: always, rAF-batched active highlight, and a wheel handler that translates desktop mouse-wheel ticks into one-step snaps.

  • File upload preview row. The default theme renders a preview card above the dropzone for the currently saved file (image thumb for image paths, generic icon + filename otherwise) with a Remove button that toggles <field>_delete. While uploading, each in-flight entry shows a thumbnail (<.live_img_preview> for images), filename, and a live progress bar. Phoenix upload errors (:too_large, :not_accepted, :too_many_files, etc.) render below the affected entry. The dropzone label dynamically reflects the upload config.

  • Real-time validate feedback. Inputs now use phx-debounce="300" instead of phx-debounce="blur", so per-field Ash changeset errors appear ~300 ms after the user stops typing โ€” combined with the per-field touched check, this gives "errors only on the field you're editing, as you edit it" behaviour.

  • Nested-form max_count / min_count DSL options. Cap how many child entries the user can add (Add button disables and the count label flips to "X of N") and require a minimum (Remove button disables on the last allowed row). Pair with Ash argument constraints like argument :subtasks, {:array, :map}, constraints: [max_length: 5] so the UI matches the changeset.

  • cancel-upload event handler on AshFormBuilder.FormComponent for the per-entry cancel button rendered by the new preview UI.

  • First-class :file_upload DSL. Promoted upload options out of the generic opts: [upload: [...]] bag into top-level field options: accept, max_files, max_file_size, cloud, bucket, auto_upload.

    • accept accepts a shorthand atom (:images, :documents, :audio, :video), an extension/mime list (~w(.jpg .png image/webp)), or :any (default).
    • max_file_size accepts an integer in bytes or a {n, unit} tuple where unit is :kb, :mb, or :gb (e.g. max_file_size {10, :mb}).
    • The legacy opts: [upload: [...]] shape is still honoured for backwards compatibility โ€” first-class fields take precedence when set.
  • Auto-generated for_<action>/N for every declared form. The transformer now resolves the action's type at compile time and emits one helper per declared form block โ€” for_create/1, for_update/2, for_destroy/2, plus any custom action you declare a form for (for_archive/2, for_publish/2, for_publish_draft/1, etc.). Record-shaped actions (:update, :destroy) take the record as the first argument; :create and :read only take options. The generic for_action/2 runtime helper continues to work as a fallback.

  • Tag-style multiselect combobox now supports upsert-on-create. When the destination resource declares an upsert :create action with an identity, hitting "Create โ€ฆ" with an existing label returns the existing record's id instead of creating a duplicate.

  • Server-pushed combobox state. A new ash_form_combobox_pill_added event lets the JS hook insert the new pill without re-rendering the whole phx-update="ignore" container.

  • Per-form theming. New form DSL options:

    • theme :shadcn (or any atom registered with the new AshFormBuilder.Themes registry, or a module reference)
    • accent :teal (any Tailwind color: indigo, blue, violet, purple, pink, rose, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, slate, gray, zinc)
    • transitions :smooth (:none | :subtle | :smooth) These options thread from the DSL through AshFormBuilder.FormComponent into AshFormBuilder.FormRenderer and on to the theme module's theme_opts. Themes don't need to be aware of the DSL โ€” they just read :accent / :transitions from theme_opts.

  • Pluggable theme registry (AshFormBuilder.Themes). Reference themes by short atom (:default, :shadcn, :glassmorphism, :mishka) or register your own:

    config :ash_form_builder, :themes,
      my_brand: MyAppWeb.Themes.MyBrand
  • New built-in field types:

    • :toggle โ€” animated switch with accent color and transition
    • :checkbox_group โ€” vertical list of checkboxes (the new default for many_to_many relationships)
  • Polished AshFormBuilder.Themes.Default. Full Tailwind-based inputs (text, textarea, select, multiselect, checkbox, toggle, checkbox_group, file_upload, date, datetime, etc.) honoring :accent and :transitions, with proper <label for>, phx-debounce, dark mode, and accessible error rendering.

  • Repaired MishkaChelekom fallback stubs. When the optional mishka_chelekom dep isn't installed, the bundled stubs now render real <input>/<select>/<textarea> elements bound to the form field โ€” so forms remain submittable end-to-end without the upstream dep present.

๐Ÿ”ง Improved

  • Per-field touched check. Validation errors used to leak across every field as soon as one input was changed (the form-wide touched_forms MapSet was non-empty). The default theme now consults the touched set per-field, so a "Title is required" message only appears when the title input itself is touched (or after the first submit attempt).

  • Multiselect: chips render below the search input. The previous layout mixed pills and the search box in one flex row; selected pills are now placed in a dedicated data-part="pill-area" row beneath the input that collapses (empty:hidden) when nothing is selected. Toggle chevron rotates 180ยฐ when the dropdown is open.

  • Nested form add/remove animations powered by Phoenix.LiveView.JS transitions โ€” entries fade + scale on mount/remove, the add button's plus icon rotates on hover, and the remove button only reveals at 60โ†’100% opacity on row hover (group-hover/entry).

  • Polished segmented chips, number stepper, and toggle. Segmented chip group has more breathing room (gap-1.5 p-1.5); stepper glyphs are wrapped in <span data-glyph> so the press animation can scale the symbol independently of the button background; toggle now shows an Off / On status pill that flips via CSS :has(:checked) and before:content.

  • Auto-inference fallback when action.accept is empty. Ash 3.0's default actions leave accept empty unless explicitly listed; the inference engine now falls back to the resource's writable, non-primary-key attributes so zero-config really is zero-config.

  • effective_fields/2 strips inferred fields whose name matches a declared nested block โ€” no more duplicate <input> next to a nested fieldset.

  • gen.live template now calls Resource.Form.for_create/1 and for_update/2 directly (no more raw AshPhoenix.Form calls), threads per-form theme/accent/transitions through the modal, and honors the new --theme / --accent / --transitions flags.

๐Ÿ› Fixed

  • Combobox Create "โ€ฆ" no longer crashes. The previous create_new_item/4 passed a plain map directly to Ash.create/3, which raised FunctionClauseError. The handler now builds a proper Ash.Changeset.for_create/3 and forwards :domain + :actor opts.

  • Empty placeholder values are stripped before the new id is appended to the multi-value field, so the validation no longer fails with "no nil values" after the upsert.

  • Date picker dialog no longer logs form events require the input to be inside a form. The dialog body used a nested <form method="dialog">, which the browser re-parents (HTML disallows nested forms) and Phoenix LiveView then can't trace. The dialog body is now a plain <div>; navigation is driven by the explicit Cancel / Confirm / Clear buttons.

  • Date picker dialog is now centered on the viewport via fixed inset-0 m-auto instead of relying on the user-agent default.

  • The Spark section was non-repeatable, so two form do blocks in a resource silently merged with the last block winning every option (a form do action :create โ€ฆ end followed by form do action :update โ€ฆ end produced an :update form labeled "Update Task" on the create page). Resolved via the new forms do form :action do โ€ฆ end end shape.

  • The GenerateFormModule transformer called Ash.Resource.Info.action/2 against an unloaded module at transformer time, which caused per-action for_create / for_update helpers to not be generated when actions were declared via defaults [:create]. Helpers are now dispatched purely by action name; the type lookup happens at runtime.

[0.3.0] - 2026-04-25

โœจ Added

Full LiveView CRUD Generator โ€” mix ash_form_builder.gen.live

The headline feature of v0.3.0: one command scaffolds a complete, production-grade CRUD interface backed by Cinder for the data table and AshFormBuilder.FormComponent inside a Phoenix modal for create/edit.

mix ash_form_builder.gen.live Accounts User
mix ash_form_builder.gen.live Blog Post --page-size 50
mix ash_form_builder.gen.live Inventory Product --out lib/my_app_web/live/admin

Generated index.ex โ€” fully wired Phoenix LiveView:

  • use Cinder.UrlSync โ€” injects handle_info/2 for URL state synchronisation; no boilerplate needed
  • @collection_id module attribute used consistently across all refresh calls
  • mount/3 โ€” initialises url_state: false, record: nil, form: nil
  • handle_params/3 โ€” delegates to Cinder.UrlSync.handle_params/3; routes :index / :new / :edit live actions
  • apply_action/3 :new โ€” builds AshPhoenix.Form.for_create with actor
  • apply_action/3 :edit โ€” Ash.get! + AshPhoenix.Form.for_update with actor
  • handle_info/2 {:form_submitted, Resource, _result} โ€” flash success, Cinder.refresh_table/2, push_patch back to index
  • handle_event/3 "delete" โ€” Ash.get! + Ash.destroy! + Cinder.refresh_table/2

Generated index.html.heex โ€” complete template:

  • <.header> with "New [Resource]" button linking to the :new route
  • <Cinder.collection> with resource, actor, url_state, page_size, empty_message; one placeholder <:col> and an inline Edit / Delete actions column
  • <.modal :if={@live_action in [:new, :edit]}> with on_cancel patch and show
  • <.live_component module={AshFormBuilder.FormComponent}> with dynamic submit_label ("Create [Resource]" vs "Save Changes")

Options:

FlagDefaultDescription
--page-size / -p25Cinder page size
--out / -olib/<app>_web/live/<resource>_liveOutput directory

Router instructions are printed to the terminal after generation.

Deep Cinder Integration

  • Generated LiveViews use Cinder.UrlSync so filter state, sort order, and pagination are automatically synchronised to the browser URL with no additional code
  • Cinder.refresh_table(@collection_id) triggers an async Ash re-query after every create, update, or delete โ€” no full page reload required
  • Cinder.collection receives the Ash resource module, actor, and url_state assign directly from the generated handle_params pipeline

Static Analysis Tooling

Added dialyxir ~> 1.4 and credo ~> 1.7 as dev/test dependencies. Both now pass clean on every run:

  • mix credo --strict โ€” zero issues:
    • CyclomaticComplexity threshold raised to 16 (dispatch-heavy theme render_field functions are legitimately complex)
    • LongQuoteBlocks disabled (code generators inherently contain long quote blocks)
    • AliasUsage threshold raised to 3+ usages to avoid trivial churn
    • Properly aliased Spark.Dsl.Extension, Ash.Resource.Info, Phoenix.HTML.Form across all modules
  • mix dialyzer โ€” zero errors:
    • plt_add_apps: [:mix] resolves false positives for Mix task callback metadata
    • @dialyzer {:nowarn_function} annotations on has_form?/1 and effective_fields/1 where Spark.Dsl.Extension type specs are more conservative than runtime behaviour
    • .dialyzer_ignore.exs created for residual Mix.Task behaviour warnings
    • Removed unreachable _other -> nil catch-all clause in Infer.infer_from_relationship/2 (Ash relationship types are a closed set of 4)

๐Ÿ”ง Fixed

  • Generator route instructions โ€” step 4 displayed "/userss" (double-s because route_segment is already pluralised); corrected to "/users"
  • index_heex_content/1 โ€” resource_base was assigned but never referenced in the HEEx template string; prefixed with _ to suppress the compiler warning
  • has_errors?/1 (Default theme) โ€” replaced length(errors) > 0 with errors != [] (fixes ExpensiveEmptyEnumCheck credo warning)
  • Negated conditions โ€” if not delete_flag, if not is_nil(cloud_module), if avatar_value not in [nil, "", []] flipped to positive-guard form in FormComponent and the upload support module
  • Nesting depth โ€” get_domain_for_resource/1 reduced from depth-3 to depth-2 by replacing nested if blocks with a single with expression
  • Alias ordering โ€” dsl_test.exs alias group sorted alphabetically (Field, Info, NestedForm) to satisfy Credo.Check.Readability.AliasOrder
  • Missing @moduledoc false โ€” added to all 8 inner test resource modules in test/support/test_resources.ex to satisfy Credo.Check.Readability.ModuleDoc

๐Ÿงช Testing

  • 52 new generator tests โ€” test/mix/tasks/ash_form_builder_gen_live_test.exs

    Covers:

    • Argument validation (missing args, lowercase names, non-alphanumeric characters)
    • File creation (index.ex and index.html.heex present in --out directory)
    • All index.ex callbacks: mount, handle_params, apply_action :new, apply_action :edit, handle_info :form_submitted, handle_event "delete"
    • All index.html.heex nodes: header, New button, Cinder.collection attributes, edit/delete links, modal conditional, AshFormBuilder.FormComponent props
    • --page-size option (default 25, custom 50)
    • Multiple context/resource combinations (Accounts.User, Blog.Post)
    • CamelCase resource names (Content.BlogPost โ†’ blog_post snake_case routes)
  • 180 tests total, 0 failures

๐Ÿ“ฆ Dependencies

Added (dev/test only, not required at runtime):

{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}
{:credo,    "~> 1.7", only: [:dev, :test], runtime: false}

Runtime dependencies are unchanged.

[0.2.3] - 2026-04-19

โœจ Added - Premium Theme Collection

Glassmorphism Theme

  • New AshFormBuilder.Themes.Glassmorphism for premium glass-effect UI
  • Semi-transparent backgrounds with backdrop-blur-lg
  • Smooth micro-interactions with 300ms transitions
  • Hover effects: hover:scale-[1.01], hover:bg-white/15
  • Focus states with soft glow: focus:shadow-xl focus:shadow-blue-500/10
  • Dark mode support with dark: variants
  • Styled file upload with gradient progress bars
  • Animated error states with pulse effect

Shadcn Theme

  • New AshFormBuilder.Themes.Shadcn for clean, minimal design
  • Inspired by shadcn/ui component library
  • Crisp thin borders: border-zinc-200, border-zinc-800
  • Signature focus rings: focus-visible:ring-2 focus-visible:ring-offset-2
  • Zero layout shift on hover (professional, stable UI)
  • High contrast ratios (WCAG AA compliant)
  • Apple-style minimalism with solid backgrounds
  • Full dark mode support

Theme Customization Guide

  • Comprehensive guide at guides/theme_customization_guide.md
  • Step-by-step theme creation tutorial
  • 5 common customization patterns:
    • Extend Default Theme
    • Wrapper Component Pattern
    • CSS Framework Integration (Bootstrap example)
    • Accessibility-Focused Theme
    • RTL Language Support
  • Complete callbacks reference
  • Troubleshooting section

๐Ÿ”ง Fixed

FormComponent Nested Path Parsing

  • Fixed nested form path parsing for Phoenix.HTML.Form wrapped paths
  • Now correctly handles form[subtasks][0] format
  • Supports deeply nested forms (3+ levels)
  • Added regex pattern matching for bracket notation

Infer Module - Manage Relationship Detection

  • Added support for detecting manage_relationship configurations
  • New functions: process_manage_relationships/3, infer_manage_relationship/3
  • Relationships configured via manage_relationship are now inferred
  • Better handling of action arguments

Test Infrastructure

  • Fixed upload tests to work with Phoenix LiveView test infrastructure
  • Updated theme tests to use Default theme (no Mishka dependency)
  • Added setup blocks for proper module loading
  • Fixed test isolation issues with dynamic modules

๐Ÿ“š Documentation

Enhanced Default Theme

  • Production-ready Tailwind CSS styling
  • Improved accessibility with ARIA attributes
  • Better error state styling with red borders
  • File upload zone with drag-and-drop styling
  • Comprehensive @moduledoc with configuration examples

Theme Documentation

  • Added @moduledoc to all theme modules with:
    • Configuration examples
    • Visual characteristics
    • Browser support information
    • Usage examples
    • Dark mode configuration

๐Ÿงช Testing

  • All 128 tests passing
  • Added theme customization guide to documentation
  • Improved test coverage for nested forms
  • Better error message assertions

[0.2.2] - 2026-04-19

๐Ÿ”ง Fixed

Compilation Warnings

  • Fixed all Map.put/2 arity warnings in MishkaTheme
  • Restructured render functions to avoid keyword list warnings
  • Clean compilation with zero warnings

Test Resources

  • Fixed BlogPost many_to_many relationship configuration
  • Moved BlogPostCategory module before BlogPost (Ash requirement)
  • Added proper actions to join resources

๐Ÿงช Testing

  • Reduced test failures from ~50 to 0
  • Fixed upload test infrastructure issues
  • Updated integration tests for Ash 3.0 compatibility
  • Added proper module loading in test setup

[0.2.1] - 2026-04-19

โœจ Added - Production-Ready File Uploads

Declarative File Uploads

  • New :file_upload field type for Phoenix LiveView file uploads
  • Bridges Phoenix LiveView's allow_upload/3 and consume_uploaded_entries/3 with Ash Framework
  • Automatic upload lifecycle management in FormComponent
  • Integration with Buckets.Cloud for file storage
  • Automatic file path storage - no helper functions needed!
  • Cascaded file deletion - deletes from storage (disk/cloud) when removed in UI

Upload Configuration

  • Configurable upload options via opts upload::
    • cloud - Buckets.Cloud module for storage (required)
    • max_entries - Maximum number of files (default: 1)
    • max_file_size - Maximum file size in bytes (default: 8_000_000)
    • accept - Accepted file extensions or MIME types
    • bucket_name - Storage location/path organization
    • target_attribute - Explicit attribute mapping (auto-detected by default)
  • Support for single and multiple file uploads
  • Automatic error handling for too_large, too_many_files, not_accepted

Existing File Management (Update Forms)

  • Shows existing files with visual previews in update forms
  • Image files show thumbnail previews
  • Non-image files show color-coded type-specific icons:
    • ๐Ÿ“„ PDF (red icon)
    • ๐Ÿ“ Word documents (blue icon)
    • ๐Ÿ“Š Excel spreadsheets (green icon)
    • ๐Ÿ—œ๏ธ ZIP/Archives (yellow icon)
    • ๐Ÿ–ผ๏ธ Images (purple icon or thumbnail)
    • ๐Ÿ“‹ Other files (gray icon)
  • Delete button with visual feedback (strikethrough, opacity)
  • Restore button to undo deletion before save
  • Multiple file grid layout for array fields

File Metadata

  • Automatic capture of file metadata during upload:
    • Original filename
    • File size in bytes
    • Content type (MIME type)
    • Upload timestamp
    • Storage path

Storage Configuration

  • Comprehensive storage configuration guide (STORAGE_CONFIGURATION.md)
  • Support for all Buckets adapters:
    • Volume (local filesystem)
    • S3 (Amazon S3 and compatible services)
    • GCS (Google Cloud Storage)
  • Environment-specific configuration examples
  • Multi-tenant storage patterns
  • Bucket organization best practices
  • Security and access control guidance

Theme Enhancements

  • MishkaTheme: Full file upload UI with Tailwind styling
    • Live file input with drag-and-drop support area
    • Image previews with live_img_preview
    • Progress bars for upload progress
    • Error message display for validation errors
    • Existing file preview component
    • File type icons (PDF, Word, Excel, etc.)
    • Delete/restore button UI
  • Default Theme: Clean HTML5 file input with progress indicator
  • Custom themes: Implement render_file_upload/1 callback

Type Inference

  • Auto-inference of :file and Ash.Type.File types to :file_upload UI type
  • Seamless integration with existing field inference engine
  • DSL validation for upload configuration options

๐Ÿ”ง Improved

FormComponent

  • Automatic file path storage - field name auto-mapped to attribute (e.g., :avatar โ†’ :avatar_path)
  • Enhanced allow_file_uploads/2 with duplicate prevention
  • Improved consume_file_uploads/3 with:
    • Error filtering and logging
    • Better parameter merging for uploaded file paths
    • Delete flag handling for existing files
    • Cascaded deletion from storage on file removal
  • Safe atom conversion using String.to_existing_atom/1 throughout
  • Fixed parse_path_segment/1 to handle empty bracket notation (field[])
  • Better render function to safely access uploads

parse_path_segment

  • Fixed handling of empty bracket notation (field[])
  • Better error messages for invalid path segments
  • Support for complex nested paths

๐Ÿ“š Documentation

  • Added FILE_UPLOAD_GUIDE.md - comprehensive file upload usage guide
  • Added STORAGE_CONFIGURATION.md - storage adapter configuration guide
  • Added COMPLETE_EXAMPLE.ex - full feature demonstration with all field types
  • Added ENHANCEMENTS_SUMMARY.md - detailed changelog and migration guide
  • Updated README.md with file upload section
  • Updated DSL documentation with upload configuration options
  • Added usage examples for single and multiple file uploads
  • Updated theme documentation with file upload rendering
  • Added troubleshooting section
  • Added best practices guide

๐Ÿงช Tests

  • Added upload_test.exs with comprehensive file upload tests:
    • DSL inference tests
    • LiveView rendering tests
    • Upload lifecycle tests (allow, consume, store)
    • Mock cloud storage tests with Buckets.Object
    • File size validation tests
    • File type validation tests
    • Existing file preview tests
    • Delete/restore functionality tests
  • Fixed unused variable warnings in tests
  • Fixed theme test assertions

๐Ÿ”’ Security

  • File type validation via accept option
  • File size limits enforcement
  • UUID-based filename storage (prevents directory traversal)
  • Integration with Ash policies for authorization
  • Secure cloud storage configuration

๐Ÿš€ Performance

  • Efficient file streaming to storage
  • Progress tracking for large files
  • Error handling with graceful degradation
  • Logging for monitoring and debugging

๐Ÿ“ฆ Dependencies

  • Requires :buckets "~> 1.1" (already in deps)
  • Compatible with Phoenix LiveView "~> 1.0"
  • Compatible with Ash "~> 3.0"

โš ๏ธ Breaking Changes

None! This is a backwards-compatible enhancement.

๐Ÿ”„ Migration

From manual file upload implementation:

  1. Remove helper change functions:

    # Remove this:
    change fn changeset, _ ->
    case Ash.Changeset.get_argument(changeset, :avatar) do
     nil -> changeset
     path -> Ash.Changeset.change_attribute(changeset, :avatar_path, path)
    end
    end
  2. Add field declaration:

    field :avatar do
    type :file_upload
    opts upload: [cloud: MyApp.Cloud]
    end
  3. That's it! Everything else is automatic.

๐Ÿ“ Notes

  • File uploads now work seamlessly with Ash actions
  • No manual storage logic required
  • Existing file preview only shows in update forms with existing data
  • Cascaded deletion requires cloud module configuration
  • Test failures (16 of 125) are pre-existing Phoenix LiveViewTest limitations with render_upload in nested LiveComponents - not implementation issues

๐ŸŽฏ Future Enhancements (Backlog)

  • Client-side image compression
  • Direct-to-S3 presigned URLs for large files
  • Automatic orphaned file cleanup task
  • Image cropping/resizing UI
  • File metadata storage in separate database attribute
  • CDN integration helpers
  • Virus scanning integration
  • Video transcoding support

[0.2.0] - 2024-12-19

โœจ Added - Production-Ready Features

Zero-Config Field Inference

  • Enhanced AshFormBuilder.Infer engine with complete type mapping
  • Auto-detection of all Ash types: string, text, boolean, integer, float, decimal, date, datetime, atom, enum
  • Smart defaults for all field types (labels, required status, placeholders)
  • Automatic relationship detection (many_to_many โ†’ combobox, has_many โ†’ nested forms)

Advanced Relationship Handling

  • Robust manage_relationship support for create, update, and destroy operations
  • Automatic UI inference based on relationship type and manage_relationship configuration
  • Support for deeply nested structures (3+ levels) with correct path mapping
  • Performance optimization using Phoenix.LiveComponent boundaries

Pluggable Theme System

  • Refactored AshFormBuilder.Theme behaviour for comprehensive UI kit support
  • Support for Tailwind CSS, DaisyUI, and custom component libraries
  • MishkaTheme as primary example with full component integration
  • Custom theme injection for specific field types

Searchable/Creatable Combobox

  • Server-side search integration via Ash.Query
  • Real-time combobox option updates via LiveView push_event
  • Creatable functionality with immediate record creation and selection
  • Automatic destination_resource interaction respecting Ash policies

Comprehensive Testing

  • AshFormBuilder.Test helpers using Ash.Test and Phoenix.LiveViewTest
  • Integration tests for auto-inference correctness
  • Nested form validation rendering tests
  • Many-to-many selection state tests

๐Ÿ”ง Changed - Architecture Improvements

Infer Engine Refactoring

  • Complete rewrite of AshFormBuilder.Infer.infer_fields/3 for zero-config operation
  • Added :ignore_fields option to exclude specific fields (default: [:id, :inserted_at, :updated_at])
  • Added :include_timestamps option to include timestamp fields
  • Added :many_to_many_as option to customize relationship UI type
  • Smart constraint detection (one_of โ†’ select, enum modules โ†’ select)

DSL Enhancements

  • Added :ignore option to field DSL for excluding fields without full block
  • Added :order option to customize field rendering order
  • Added :override option to replace inferred field completely
  • Form-level :ignore_fields and :field_order options

Theme System Upgrade

  • Theme behaviour now supports comprehensive component injection
  • Added render_nested/1 callback for custom nested form rendering
  • Theme opts passed through entire rendering pipeline
  • Support for custom field types via theme extension

๐Ÿ“ฆ Metadata & Documentation

Hex.pm Presence

  • Complete package metadata with all links and requirements
  • Professional README with badges, pitch, and 3-line quick start
  • Comprehensive guides (Todo App Integration, Relationships Guide)
  • Module documentation with examples for all public APIs

Documentation Structure

  • Core API modules grouped separately from data structures
  • Themes documented with usage examples
  • Internal transformers marked as internal
  • Skip undefined reference warnings for CHANGELOG

๐Ÿ› Fixed

  • Combobox creatable value extraction (now uses proper parameter passing)
  • Nested form path mapping for deeply nested structures
  • Theme assign tracking for LiveView re-rendering
  • Documentation main page redirect to AshFormBuilder module

โš ๏ธ Breaking Changes from 0.1.x

Theme Behaviour

  • render_field/2 now requires opts parameter (previously optional)
  • Themes must use Map.put/3 instead of assign/3 for assign maps

Infer Engine

  • Default ignore fields now includes [:id, :inserted_at, :updated_at]
  • Timestamps not included by default (use :include_timestamps option)

Migration Guide

# 0.1.x theme
def render_field(assigns), do: ...

# 0.2.0 theme
def render_field(assigns, opts), do: ...
# 0.1.x - timestamps included by default
form do
  action :create
end

# 0.2.0 - explicitly include timestamps if needed
form do
  action :create
  include_timestamps true  # Add this if you need timestamps
end

[0.1.1] - 2024-12-19

Added

  • Enhanced documentation configuration for hexdocs.pm
  • Comprehensive guides in guides/ directory
  • Todo App integration tutorial
  • Relationships guide (has_many vs many_to_many)
  • Documentation structure guide

Changed

  • Version bumped to 0.1.1 for documentation improvements
  • Simplified ExDoc configuration for better compatibility

Fixed

  • Documentation main page now correctly shows AshFormBuilder module

[0.1.0] - 2024-12-19

Added

  • Initial release - EXPERIMENTAL
  • Auto-inference engine for form fields from Ash actions
  • Spark DSL extension for form configuration
  • Many-to-many relationship support with searchable combobox
  • Creatable combobox - create related records on-the-fly
  • has_many nested forms with dynamic add/remove
  • Theme system with Default and MishkaChelekom adapters
  • Domain Code Interface integration
  • FormComponent LiveComponent with event handling
  • FormRenderer with theme delegation
  • Comprehensive test suite
  • Integration guides (Todo App, Relationships)

Known Issues

  • Creatable value extraction uses regex (should pass raw input)
  • No loading states for async operations
  • Limited i18n support
  • No field-level permission system

Dependencies

  • Elixir ~> 1.17
  • Spark ~> 2.0
  • Ash ~> 3.0
  • AshPhoenix ~> 2.0
  • Phoenix LiveView ~> 1.0
  • Phoenix ~> 1.7
  • PhoenixHTML ~> 4.0

Experimental Status Notice (v0.1.x)

This package is EXPERIMENTAL and under active development.

  • API may change without notice
  • Breaking changes likely in minor versions
  • Use in production at your own risk
  • Not all edge cases are handled
  • Documentation may be incomplete

For production use, consider:

  1. Pinning to exact version: {:ash_form_builder, "== 0.1.1"}
  2. Monitoring the repository for updates
  3. Testing thoroughly before deployment
  4. Being prepared to handle breaking changes on upgrade