Migration guide for v1.x.x to v2.x.x
This guide explains how to migrate your apps after the v2 release’s package and artifact restructure. It covers three paths: staying on v1 via legacy modules, migrating from v1 to v2, and moving from v2-beta to the final v2. For feature-level differences and what’s new, see: What’s new in 2.0.0What changed at a glance
- Dependencies: use standard
io.joyfill:*artifacts for v2, orio.joyfill:legacy-*to remain on v1 (details, stay on v1) - Package names: v2-beta code under
joyfill2moved tojoyfillin v2 — rename imports fromjoyfill2→joyfill(details) - Event API: legacy
FieldEventhas been replaced byComponentEvent.*— useComponentEvent.FieldEvent(standalone fields) andComponentEvent.CellEvent(table cells) (details) - Behavior notes: most imports remain identical for v1→v2 because the package is still
joyfill; some v1 UI components may not exist in v2 — check v2 docs for alternatives (details)
Dependencies changes
- Replace legacy artifacts with the standard ones:
- io.joyfill:legacy-compose → io.joyfill:compose
- io.joyfill:legacy-models → io.joyfill:models
- io.joyfill:legacy-builder → io.joyfill:builder
- io.joyfill:legacy-api → io.joyfill:api
- Keep using
joyfill.*imports. - Example usage:
FieldEvent → ComponentEvent.* (events)
Summary- v1 used a single
FieldEventfor all field callbacks. - v2 unifies events under
ComponentEvent.*with two concrete types:ComponentEvent.FieldEvent<E>for standalone fields (text, number, image, signature, etc.)ComponentEvent.CellEvent<E>for table cells (row-aware events)
- Handler parameter types changed accordingly in
Form/components.
- The v2 architecture standardizes how components emit and consume events and makes table events first-class by including row/column context.
- v1 (legacy):
joyfill.FieldEvent - v2:
joyfill.ComponentEvent.FieldEventandjoyfill.ComponentEvent.CellEvent
- Common in both versions:
fieldId,fieldIdentifier,pageId,id(document id),identifier(document identifier),fileId,fieldPositionId
- v2 additions/notes:
source: the typed editor instance (e.g.,ImageEditor,TextEditor)multi: available when the underlying component is a file component (e.g., image with multi-upload)- Cell-only:
rowIds,columnId,schemaId,parentPath
- General field handlers (change/focus/blur)
- v1 (legacy Form):
- v2 (Form/components):
- File upload/capture handlers (image/signature/barcode)
- v1:
- v2:
- Table cell events
- v2 introduces
CellEventfor row-aware callbacks used by table components and their editors:
- Replace callback parameter types:
FieldEvent→ComponentEvent<*>when used at the Form level- For table-specific handlers: prefer
ComponentEvent.CellEvent<*> - For single-field components: prefer
ComponentEvent.FieldEvent<*>
- Update
whenbranches to handle bothFieldEventandCellEventwhere applicable. - If you previously relied on
attachmentsin events: v2 surfaces file uploads through file editors and returns should come from your handler;attachmentson events is not required in typical flows.
ComponentEventis generic on the editor type (E : ComponentEditor). When you need editor-specific behavior, checke.sourcewithis ImageEditoretc.
- v2 event system overview: architecture/v2/event-system.md
FAQ
Q: Why do both v1 and v2 havejoyfill.Form?
A: v1 code was moved into legacy-* modules but retained the exact same package names for easier migration. Which Form you get depends on whether your dependency is from legacy-* or from the standard modules.
Q: How do I verify I’m on v2?
- Ensure you’re using the standard artifacts (no
legacy-prefix). - Confirm your imports are
joyfill.*and that you do NOT havejoyfill2.*anywhere.
- Some components may be missing in v2 compared to v1, but v2 offers many new features and improved architecture. See the v2 docs for details.
Related Documentation
- Architecture Overview: architecture/README.md
- V2 Overview: architecture/v2/README.md
- V2 UI Components: architecture/v2/ui-components.md
- V2 Editor Pattern: architecture/v2/editor-pattern.md
- V2 API Integration: architecture/v2/api-integration.md
Important context
- Prior to v2 release, we had:
- v1 under the
joyfillpackage - v2-beta under the
joyfill2package
- v1 under the
- With the v2 release:
- v2 now lives under the
joyfillpackage - Legacy v1 classes were moved into separate legacy modules, but kept the same
joyfillpackage names for source compatibility - Practically, both legacy and v2 expose symbols like
joyfill.Form. Which one you use depends on the dependency you add.
- v2 now lives under the
- V1 → V2: swap your dependencies from legacy modules to v2 modules. Most imports remain identical because the package is still
joyfill. - V2-beta → V2: rename your imports from
joyfill2tojoyfill. No other code changes should be required.
Stay on v1 (Legacy Modules)
[!CAUTION] This is not RECOMMENDED. This is a temporary path for those who want to continue using v1 for a short period of time.Summary
- If you want to continue using the legacy v1 implementation for a period, switch your dependencies to the
legacy-*artifacts. - Imports remain
joyfill.*because legacy modules preserve the same package names.
- Replace standard artifacts with legacy ones if you were previously on the standard artifacts but wish to remain on v1:
io.joyfill:compose→io.joyfill:legacy-composeio.joyfill:models→io.joyfill:legacy-modelsio.joyfill:builder→io.joyfill:legacy-builderio.joyfill:api→io.joyfill:legacy-api
- Ensure your imports remain
joyfill.*and notjoyfill2.*. - Confirm you’re pulling
legacy-*artifacts in your dependency tree.
- This path is intended for temporary continuity. Plan to migrate to v2 soon.