@msbci/form-editor
v1.3.9
Published
Visual form builder — 3-panel editor with drag & drop
Readme
@msbci/form-editor
Visual form builder — 3-panel editor with drag & drop. Create and edit forms defined by @msbci/form-core schemas.
Installation
npm install @msbci/form-editor @msbci/form-renderer @msbci/form-coreUsage
import { FormEditor } from '@msbci/form-editor'
<FormEditor
theme={myTheme}
dataSources={myConnectors}
adapter={{
loadForm: (id) => api.getForm(id),
saveForm: (form) => api.saveForm(form),
loadFormTypes: () => api.getFormTypes(),
saveFormType: (type) => api.saveFormType(type),
}}
onChange={(schema) => console.log('Form updated', schema)}
onSave={() => console.log('Saved')}
/>IEditorAdapter
The editor makes no direct API calls. All persistence goes through the adapter:
interface IEditorAdapter {
loadForm?: (id: string) => Promise<IFormDefinition>
saveForm?: (form: IFormDefinition) => Promise<void>
loadFormTypes?: () => Promise<IFormType[]>
saveFormType?: (type: IFormType) => Promise<void>
}Pass adapter to FormEditor — the host app controls all backend communication.
Features
| Feature | Description |
|---------|-------------|
| 3-panel layout | Toolbox (left) / Canvas (center) / Properties (right) |
| Drag & drop | Drag fields from toolbox to canvas pages (dnd-kit) |
| Undo / Redo | 50-step history with action descriptions |
| ConditionBuilder | Visual AND/OR condition constructor with 15 operators |
| DataSourceSelector | Select connector + map dependency keys to variables |
| Live preview | Switch to Preview mode to test with FormRenderer |
| JSON view | Inspect raw form schema in the editor |
| Export / Import | JSON export with schema version envelope |
| Zustand store | Full CRUD: pages, rosters, variables, selection, view |
ConditionBuilder
Build conditions visually — no expression syntax required:
- Choose action: Show, Hide, Validate, Require, Read-only, Set Value
- Add rules: Variable → Operator → Value
- Combine with AND / OR logic
- Expression preview auto-generated
- Error message field for validation rules
- Target variable + value for setValue actions
DataSourceSelector
Connect select/multiselect/radio fields to registered data sources:
- Dropdown of available
IDataSourceConnectorinstances - Add dependency keys (e.g.
parentId,countryId) - Map each key to a form variable
- Cascading updates handled automatically by the renderer
Theme
Uses the same IMosobiTheme system as @msbci/form-renderer:
<FormEditor theme={myTheme} dataSources={connectors} adapter={adapter} />v1.3.9
- Toolbox alignée sur
VariableTypecomplet —ToolboxSimpleetToolbox(DnD) listent désormais les 22 types sans omission. Ajouts :ToolboxSimple:listradio(Sélection),photo(Médias),panel+richtext(Avancé).Toolbox(DnD) :email(Texte),listradio(Sélection),photo(Médias),rating+panel+richtext(Avancé).
- Icônes assignées :
≡(listradio),📷(photo),▭(panel),📝(richtext) — cohérence avec le mix ASCII/émoji existant. - Tous les labels viennent de
labels.toolbox.types.*(clés déjà ajoutées en v1.3.8, FR + EN). - Aucun changement d'API ; 167 tests inchangés.
v1.3.8
VariablePropertiesaligné surVariableTypecomplet (form-core v1.3.3) — le<select>Type liste désormais les 22 types dans l'ordre Texte → Sélection → Date/Heure → Médias → Avancé. Conséquence : sélectionner une variable de typeimage(ouemail,photo,listradio,panel,richtext) affiche bien le bon type dans le panneau au lieu de retomber surtext(et le risque associé d'écraser le type via un clic involontaire est éliminé).- Labels FR/EN ajoutés pour
listradio,photo,panel,richtextdanslabels.toolbox.types.*. Single source of truth utilisée à la fois par Toolbox(Simple) et VariableProperties. - Aucun changement d'API, 167 tests inchangés.
v1.3.7
- Hotfix toolbox DnD : le type
imagen'apparaissait pas dansToolbox(DnD), bien que la variable soit fonctionnelle dans le renderer et exposée dansToolboxSimple. La section MÉDIAS contient désormais Fichier · Image · GPS dans les deux variantes ;fileetgpssont sortis de Avancé pour cohérence avec ToolboxSimple. - Aucun changement d'API, 167 tests inchangés.
v1.3.6
- Sections de configuration multi-upload dans
VariableProperties:- Section « Configuration fichier » (visible si
type === 'file') —maxFiles,minFiles,accept. Le selectmaxFilespropose[1, 2, 3, 5, 10, illimité]mappés sur[1, 2, 3, 5, 10, undefined]. - Section « Configuration image » (visible si
type === 'image') —maxImages,minImages, case à cocherallowCamera. - Les deux sections nettoient l'objet à chaque édition : un payload vide est remonté à
undefinedpour rester invisible côté schéma.
- Section « Configuration fichier » (visible si
- Labels FR/EN ajoutés :
properties.fileConfig*(6 clés) etproperties.imageConfig*(4 clés). - Pas de nouveau test côté editor (la couverture vit dans form-core et form-renderer). 167 tests inchangés.
v1.3.5
- ScopeManagerDialog — nouveau dialog modal qui pilote le CRUD des
IScope. Bouton "Scopes" ajouté dans la barre d'outils (data-testid="toolbar-scopes") entre ⚙ et+ Page. Création (nom + code auto), édition inline du nom au clic, suppression avec confirmation. Si le serveur renvoie 409 (scope rattaché à des forms/templates/dataSources), le message d'erreur est affiché inline en rouge dans la zone de confirmation. - VariableTemplateManager — sous-dialog ouvert depuis le bouton "Gérer les variables →" de chaque scope (data-testid
scope-manage-variables-{code}). Rechargeadapter.loadTemplates(scopeId)au mount (liste authoritative du scope, indépendamment du formulaire courant). Updates optimistes après chaque mutation (pas de refetch). - Formulaire d'édition template progressif :
- Toujours visible :
code(read-only en édition),name(LocalizedField, read-only en édition),variableType,description,placeholder, flagsisRequired/isReadonly/isHidden. - Conditionnels :
OptionsEditorsitype ∈ [select, multiselect, radio, checkbox, listradio],expressionsicalculated,dataSourceId(dropdown alimenté paravailableDataSources) si[select, multiselect]. - Section repliable "Avancé" :
validationRules,conditions,styleen JSON (validation client avant submit).
- Toujours visible :
IEditorAdapterétendu :createScope,updateScope,deleteScope,createTemplate,updateTemplate,deleteTemplate— toutes optionnelles. Les patchesupdateTemplateexcluent typedef-sidecodeetname(immuables côté serveur).- Labels FR/EN :
toolbar.scopes,toolbar.manageScopesTitle, blocsscopeManager.*etvariableTemplateManager.*(titre paramétrable, confirmations, badges read-only, ARIA labels par row). - 16 nouveaux tests RTL (
scopeManager.test.tsx×8 +variableTemplateManager.test.tsx×8) — 167 tests passants.
v1.3.4
- DataSourceConfigManager — nouveau dialog modal (
/dialogs/DataSourceConfigManager.tsx) qui pilote le CRUD desIDataSourceConfigcôté admin. Liste filtrable par scope (badge de provenance), formulaire d'ajout/édition (code, name, URL, method, queryParam, value/label fields, headers password-masked, dépendances). Bouton "Sources" ajouté dans la barre d'outils (data-testid="toolbar-datasources"). IEditorAdapterétendu :loadDataSources(scopeId),createDataSource(scopeId, data),updateDataSource(id, data),deleteDataSource(id)— toutes optionnelles.- Store : nouveau
availableDataSources: IDataSourceConfig[]+ settersetAvailableDataSources(). Hors undo/redo (UI state). Chargé parFormEditorviaPromise.all(scopeIds.map(loadDataSources))+ dédup parcode(premier scope gagne, comme les templates). DataSourceSelectorlit désormais le store en plus de la prop legacyavailableConnectors— les configs admin l'emportent sur les connecteurs hardcodés du host.- Labels FR/EN :
toolbar.dataSources,toolbar.manageDataSourcesTitle, bloc completdataSourceManager.*(titre dialog, formulaire, badges, confirmations). - 6 nouveaux tests RTL (
dataSourceConfigManager.test.tsx) — 151 tests passants.
v1.3.3
- Régression zone vide canvas corrigée — un clic sur la zone vide entre les pages déclenche désormais
select({ type: 'form' })et ouvre les propriétés du formulaire (gardee.target === e.currentTargetpour ne pas capturer les clics enfants) - Nouveau bouton ⚙ Propriétés du formulaire dans la barre d'outils (header) — accès direct au panneau, indépendamment de l'état du canvas (
data-testid="toolbar-form-properties") - Multi-scopes :
IFormDefinition.scopeIds[]exposé via unScopesSelectordansFormProperties(ajout par dropdown, suppression par ×, réordonnement par ▲/▼ — l'ordre = priorité) - Toolbox Variables : affiche le message
noScopesiscopeIdsest vide ou absent FormEditor: chargement des templates viaPromise.all(scopeIds.map(loadTemplates))+ déduplication parcode(premier scope gagne)- Nouveau adapter optionnel
loadScopes?: () => Promise<IScope[]>+ étatavailableScopes(hors undo/redo) consommé par leScopesSelector - Labels FR/EN :
toolbar.formProperties,properties.scopes,properties.scopesHint,properties.noScopesAvailable,properties.moveScopeUp,properties.moveScopeDown,properties.removeScope - 10 nouveaux tests RTL (
scopesMigration.test.tsx) — 145 tests passants
v1.3.2
- Nouveau
ConditionsModal— édition des conditions dans un modal dédié (700 px, focus trap maison, fermeture uniquement via ✕ / Annuler / Appliquer ; l'overlay n'est volontairement pas cliquable) - Mode Saisie manuelle dans le modal :
<textarea>éditable avec coloration syntaxique sans dépendance externe (technique mirror textarea/div, tokenizer maison pourshow/hide/setValue/validate/require/readonly/ConditionEval,${VARIABLE}, opérateurs, strings, nombres) - Bug fix : la condition
ConditionEval(...)d'une règlevalidateest désormais éditable librement via le mode manuel — l'admin peut taper l'expression complète sans passer par le constructeur visuel - Toggle
[Constructeur visuel] [Saisie manuelle]— warning explicite si l'expression manuelle est trop complexe pour le builder VariableProperties: remplacement duConditionBuilderinline par un bouton « Configurer les conditions » + aperçu monospace des formules en lecture seule- 10 nouveaux tests RTL (
conditionsModal.test.tsx) — 641 tests passants
v1.3.1
DndManagerinterne —<FormEditor />activera désormais le DnD complet sans wrapper externe- Canvas DnD : drag-handle ⠿ dédié sur le header des pages (a11y + keyboard sensor)
- Canvas DnD : bouton « + Ajouter un champ au roster » + zone de drop sur le corps du roster
createDragEndHandler(actions, getForm)exporté comme factory pure (testable sans React)resolveTargetcorrigé :rosterCodetransmis correctement lors d'un drop sur un roster- Compat :
Toolbox/Canvas(DnD) deviennent les défauts ;ToolboxSimple/CanvasSimplerestent disponibles ;Wrapperdéprécié (warning console one-shot)
v1.3.0
- Section ROSTER dans la toolbox (4 types : check, list, collection, collection extended) — drag & drop
- Onglet Variables : référentiel par scope, recherche par code+nom, ajout par clic ou drag
- Variable liée : bannière 🔗, champs
code/namegrisés, surcharge locale par champ setVariableOverride,resetVariableOverride— double écriture overrides + miroir sur la variableaddVariableFromTemplate(pageCode, template, rosterCode?)— dénormalisation du templateIEditorAdapter.loadTemplates?: (scopeId) => Promise<IVariableTemplate[]>(optionnel)availableTemplates+setAvailableTemplates— état UI hors undo/redo- Bouton « + Add Roster » supprimé (la toolbox est désormais le seul point d'entrée)
IFormPage.items[]source de vérité pour le canvas — variables et rosters réordonnables ensemble viamoveItem- 34 nouveaux tests (115 total)
v1.2.0
LocalizedInput: saisie bilingue avec onglets FR/EN dans le panneau propriétésLocalizedField: wrapper label +LocalizedInput- Section « Langues » dans
FormProperties: configurerlangConfig, ajouter/retirer des langues - Confirmation avant suppression d'une langue (
stripLangFromForm) - DefaultLang verrouillée (UX safety net)
flattenLocalizedexporté publiquement- 15 nouveaux tests (81 total)
What's new in v1.1.0
ConditionBuildergains an optionalrosterContextprop. When provided, conditions are validated against the roster scope (variables in the same row, backward-jump detection, self-reference rules, circular dependencies) viaRosterConditionEnginefrom@msbci/form-corev1.1.0. Errors are surfaced inline under the condition preview.VariablePropertiesauto-detects when a variable lives inside a roster and forwards the scope context toConditionBuilder. No change required in host applications.- Aligned with
@msbci/form-corev1.1.0 (4 new variable types, extendedIFieldResponseMetadata,IFormRoster.collectionConfig).
License
Copyright (c) 2026 MOSOBI — All rights reserved. Commercial license required. Contact: [email protected]
