@msbci/form-editor 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +297 -6
- package/dist/index.d.ts +297 -6
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -16
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { ComponentType } from 'react';
|
|
3
|
-
import { IFormDefinition, IFormPage, IFormRoster, IFormVariable, IFormType, IDataSourceConnector, IConditionRule } from '@msbci/form-core';
|
|
2
|
+
import { ReactNode, ComponentType } from 'react';
|
|
3
|
+
import { IFormDefinition, IFormPage, IFormRoster, IFormVariable, IFormType, IDataSourceConnector, IConditionRule, IRosterVariableRef } from '@msbci/form-core';
|
|
4
4
|
export { IDataSourceConnector, IFormDefinition, IFormPage, IFormRoster, IFormVariable, IMosobiThemeBase } from '@msbci/form-core';
|
|
5
5
|
import * as zustand from 'zustand';
|
|
6
6
|
|
|
@@ -56,7 +56,7 @@ interface EditorState {
|
|
|
56
56
|
/** Editor actions */
|
|
57
57
|
interface EditorActions {
|
|
58
58
|
setForm: (form: IFormDefinition) => void;
|
|
59
|
-
updateFormMeta: (updates: Partial<Pick<IFormDefinition, 'name' | 'code' | 'description' | 'formTypeId' | 'version'>>) => void;
|
|
59
|
+
updateFormMeta: (updates: Partial<Pick<IFormDefinition, 'name' | 'code' | 'description' | 'formTypeId' | 'version' | 'langConfig'>>) => void;
|
|
60
60
|
addPage: (page: IFormPage) => void;
|
|
61
61
|
updatePage: (pageCode: string, updates: Partial<IFormPage>) => void;
|
|
62
62
|
removePage: (pageCode: string) => void;
|
|
@@ -86,6 +86,278 @@ interface EditorActions {
|
|
|
86
86
|
}
|
|
87
87
|
type EditorStore = EditorState & EditorActions;
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* IEditorLabels — full label dictionary for the FormEditor UI.
|
|
91
|
+
*
|
|
92
|
+
* Pattern A (zero external dependency): consumers pass a `labels` prop to
|
|
93
|
+
* FormEditor and the values flow through React context to every sub-component.
|
|
94
|
+
* French is the absolute default; English ships out of the box; any other
|
|
95
|
+
* language can be added by providing a (deep-)partial override.
|
|
96
|
+
*
|
|
97
|
+
* Functions in this interface format strings with runtime arguments (counts,
|
|
98
|
+
* names, indices). They are *replaced wholesale* by deepMerge, not merged.
|
|
99
|
+
*/
|
|
100
|
+
type DeepPartial<T> = T extends (...args: never[]) => unknown ? T : T extends object ? {
|
|
101
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
102
|
+
} : T;
|
|
103
|
+
interface IEditorLabels {
|
|
104
|
+
toolbar: {
|
|
105
|
+
formNamePlaceholder: string;
|
|
106
|
+
unsaved: string;
|
|
107
|
+
addPage: string;
|
|
108
|
+
types: string;
|
|
109
|
+
manageFormTypesTitle: string;
|
|
110
|
+
undo: string;
|
|
111
|
+
redo: string;
|
|
112
|
+
save: string;
|
|
113
|
+
saving: string;
|
|
114
|
+
export: string;
|
|
115
|
+
import: string;
|
|
116
|
+
viewEditor: string;
|
|
117
|
+
viewPreview: string;
|
|
118
|
+
viewJson: string;
|
|
119
|
+
};
|
|
120
|
+
toolbox: {
|
|
121
|
+
searchPlaceholder: string;
|
|
122
|
+
addPageFirst: string;
|
|
123
|
+
groupText: string;
|
|
124
|
+
groupSelection: string;
|
|
125
|
+
groupDateTime: string;
|
|
126
|
+
groupMedia: string;
|
|
127
|
+
groupAdvanced: string;
|
|
128
|
+
/**
|
|
129
|
+
* Shared variable-type labels. Re-used by both Toolbox(Simple) and
|
|
130
|
+
* VariableProperties (single source of truth).
|
|
131
|
+
*/
|
|
132
|
+
types: {
|
|
133
|
+
text: string;
|
|
134
|
+
textarea: string;
|
|
135
|
+
number: string;
|
|
136
|
+
email: string;
|
|
137
|
+
select: string;
|
|
138
|
+
multiselect: string;
|
|
139
|
+
radio: string;
|
|
140
|
+
checkbox: string;
|
|
141
|
+
date: string;
|
|
142
|
+
datetime: string;
|
|
143
|
+
time: string;
|
|
144
|
+
file: string;
|
|
145
|
+
image: string;
|
|
146
|
+
gps: string;
|
|
147
|
+
rating: string;
|
|
148
|
+
calculated: string;
|
|
149
|
+
hidden: string;
|
|
150
|
+
label: string;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
canvas: {
|
|
154
|
+
/** CanvasSimple — no page in form. */
|
|
155
|
+
emptyStateNoPage: string;
|
|
156
|
+
/** Canvas (dnd) — no page in form. */
|
|
157
|
+
emptyStateNoPageDnd: string;
|
|
158
|
+
/** Empty page — invites to add a field. */
|
|
159
|
+
emptyStatePage: string;
|
|
160
|
+
/** Fallback when page.name is blank. */
|
|
161
|
+
unnamedPage: string;
|
|
162
|
+
/** Badge on repeatable pages. */
|
|
163
|
+
repeatable: string;
|
|
164
|
+
/** "X fields · Y rosters" — count helper for the page header. */
|
|
165
|
+
fieldsRostersCount: (fields: number, rosters: number) => string;
|
|
166
|
+
/** "X fields" — count helper for the Canvas (dnd) page header. */
|
|
167
|
+
fieldsCount: (fields: number) => string;
|
|
168
|
+
/** "X vars" — count helper for the roster header. */
|
|
169
|
+
rosterVarsCount: (vars: number) => string;
|
|
170
|
+
/** Button: add a roster to the current page. */
|
|
171
|
+
addRoster: string;
|
|
172
|
+
/** Button: add a variable inside a roster. */
|
|
173
|
+
addFieldToRoster: string;
|
|
174
|
+
/** Prefix shown before the pilot variable code on a roster header. */
|
|
175
|
+
pilotPrefix: string;
|
|
176
|
+
/** Default name when auto-creating a roster. */
|
|
177
|
+
newRosterName: string;
|
|
178
|
+
/** Default name when auto-creating a roster variable. */
|
|
179
|
+
newFieldName: string;
|
|
180
|
+
/** Default name when auto-creating a toolbox-spawned variable.
|
|
181
|
+
* Receives the type label (e.g. "Texte court") and returns the full name. */
|
|
182
|
+
newVariableName: (typeLabel: string) => string;
|
|
183
|
+
/** Tooltip on the "has conditions" indicator. */
|
|
184
|
+
hasConditionsTitle: string;
|
|
185
|
+
/** Tooltip on the "data source connected" indicator. */
|
|
186
|
+
dataSourceConnectedTitle: string;
|
|
187
|
+
};
|
|
188
|
+
properties: {
|
|
189
|
+
/** Header of the right-hand properties panel. */
|
|
190
|
+
title: string;
|
|
191
|
+
name: string;
|
|
192
|
+
code: string;
|
|
193
|
+
description: string;
|
|
194
|
+
placeholder: string;
|
|
195
|
+
version: string;
|
|
196
|
+
formType: string;
|
|
197
|
+
noType: string;
|
|
198
|
+
formSummary: (pages: number, variables: number) => string;
|
|
199
|
+
pageSummary: (variables: number, rosters: number) => string;
|
|
200
|
+
rosterSummary: (variables: number, options: number) => string;
|
|
201
|
+
repeatablePage: string;
|
|
202
|
+
minInstances: string;
|
|
203
|
+
maxInstances: string;
|
|
204
|
+
controlVariableCode: string;
|
|
205
|
+
instanceLabel: string;
|
|
206
|
+
rosterType: string;
|
|
207
|
+
pilotVariableCode: string;
|
|
208
|
+
rosterTypes: {
|
|
209
|
+
check: string;
|
|
210
|
+
list: string;
|
|
211
|
+
collection: string;
|
|
212
|
+
collection_extend: string;
|
|
213
|
+
};
|
|
214
|
+
type: string;
|
|
215
|
+
ratingStyle: string;
|
|
216
|
+
ratingStyles: {
|
|
217
|
+
star: string;
|
|
218
|
+
number: string;
|
|
219
|
+
color: string;
|
|
220
|
+
};
|
|
221
|
+
layout: string;
|
|
222
|
+
startNewRow: string;
|
|
223
|
+
columnSpan: string;
|
|
224
|
+
columnSpanAuto: string;
|
|
225
|
+
columnSpanHalf: string;
|
|
226
|
+
columnSpanThird: string;
|
|
227
|
+
columnSpanFull: string;
|
|
228
|
+
required: string;
|
|
229
|
+
readonly: string;
|
|
230
|
+
hidden: string;
|
|
231
|
+
expression: string;
|
|
232
|
+
langConfigSection: string;
|
|
233
|
+
langConfigAvailable: string;
|
|
234
|
+
langConfigDefault: string;
|
|
235
|
+
langConfigStrategy: string;
|
|
236
|
+
langConfigStrategies: {
|
|
237
|
+
prop: string;
|
|
238
|
+
browser: string;
|
|
239
|
+
selector: string;
|
|
240
|
+
auto: string;
|
|
241
|
+
};
|
|
242
|
+
langConfigSelectorPosition: string;
|
|
243
|
+
langConfigPositions: {
|
|
244
|
+
top: string;
|
|
245
|
+
bottom: string;
|
|
246
|
+
};
|
|
247
|
+
langConfigConfirmRemove: (lang: string) => string;
|
|
248
|
+
langConfigConfirmYes: string;
|
|
249
|
+
langConfigConfirmNo: string;
|
|
250
|
+
};
|
|
251
|
+
optionsEditor: {
|
|
252
|
+
optionsCount: (count: number) => string;
|
|
253
|
+
noOptions: string;
|
|
254
|
+
optionLabelPlaceholder: string;
|
|
255
|
+
optionValuePlaceholder: string;
|
|
256
|
+
addOption: string;
|
|
257
|
+
optionLabelAria: (index: number) => string;
|
|
258
|
+
optionValueAria: (index: number) => string;
|
|
259
|
+
removeOptionAria: (index: number) => string;
|
|
260
|
+
};
|
|
261
|
+
conditionBuilder: {
|
|
262
|
+
conditionsCount: (count: number) => string;
|
|
263
|
+
addCondition: string;
|
|
264
|
+
rulesCount: (rules: number) => string;
|
|
265
|
+
addRule: string;
|
|
266
|
+
action: string;
|
|
267
|
+
match: string;
|
|
268
|
+
all: string;
|
|
269
|
+
any: string;
|
|
270
|
+
actions: {
|
|
271
|
+
show: string;
|
|
272
|
+
hide: string;
|
|
273
|
+
validate: string;
|
|
274
|
+
require: string;
|
|
275
|
+
readonly: string;
|
|
276
|
+
setValue: string;
|
|
277
|
+
};
|
|
278
|
+
operators: {
|
|
279
|
+
equals: string;
|
|
280
|
+
not_equals: string;
|
|
281
|
+
greater_than: string;
|
|
282
|
+
less_than: string;
|
|
283
|
+
greater_than_or_equal: string;
|
|
284
|
+
less_than_or_equal: string;
|
|
285
|
+
contains: string;
|
|
286
|
+
not_contains: string;
|
|
287
|
+
is_empty: string;
|
|
288
|
+
is_not_empty: string;
|
|
289
|
+
starts_with: string;
|
|
290
|
+
ends_with: string;
|
|
291
|
+
in: string;
|
|
292
|
+
not_in: string;
|
|
293
|
+
between: string;
|
|
294
|
+
regex: string;
|
|
295
|
+
};
|
|
296
|
+
variablePlaceholder: string;
|
|
297
|
+
valuePlaceholder: string;
|
|
298
|
+
errorMessage: string;
|
|
299
|
+
errorMessagePlaceholder: string;
|
|
300
|
+
targetVariableCode: string;
|
|
301
|
+
targetVariablePlaceholder: string;
|
|
302
|
+
valueToSet: string;
|
|
303
|
+
valueToSetPlaceholder: string;
|
|
304
|
+
};
|
|
305
|
+
dataSource: {
|
|
306
|
+
title: string;
|
|
307
|
+
connector: string;
|
|
308
|
+
none: string;
|
|
309
|
+
connectedTo: string;
|
|
310
|
+
dependencies: (count: number) => string;
|
|
311
|
+
selectVariable: string;
|
|
312
|
+
dependencyKeyPlaceholder: string;
|
|
313
|
+
addDependency: string;
|
|
314
|
+
};
|
|
315
|
+
formTypesDialog: {
|
|
316
|
+
dialogAriaLabel: string;
|
|
317
|
+
title: string;
|
|
318
|
+
closeAriaLabel: string;
|
|
319
|
+
noTypes: string;
|
|
320
|
+
confirmDelete: string;
|
|
321
|
+
deleteConfirm: string;
|
|
322
|
+
deleteCancel: string;
|
|
323
|
+
removeTypeAria: (name: string) => string;
|
|
324
|
+
newTypeNamePlaceholder: string;
|
|
325
|
+
newTypeCodePlaceholder: string;
|
|
326
|
+
addButton: string;
|
|
327
|
+
};
|
|
328
|
+
formEditor: {
|
|
329
|
+
previewMissing: string;
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* French labels for FormEditor — absolute default.
|
|
335
|
+
*
|
|
336
|
+
* Any consumer that does not pass a `labels` prop will see this content.
|
|
337
|
+
*/
|
|
338
|
+
|
|
339
|
+
declare const frLabels: IEditorLabels;
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* English labels for FormEditor — opt-in via `labels` prop.
|
|
343
|
+
*/
|
|
344
|
+
|
|
345
|
+
declare const enLabels: IEditorLabels;
|
|
346
|
+
|
|
347
|
+
interface EditorLabelsProviderProps {
|
|
348
|
+
labels: IEditorLabels;
|
|
349
|
+
children: ReactNode;
|
|
350
|
+
}
|
|
351
|
+
declare function EditorLabelsProvider({ labels, children, }: EditorLabelsProviderProps): react_jsx_runtime.JSX.Element;
|
|
352
|
+
/** Read the resolved labels. Defaults to French if no provider is mounted. */
|
|
353
|
+
declare function useLabels(): IEditorLabels;
|
|
354
|
+
/**
|
|
355
|
+
* Recursively merges `override` into `base`. Functions, arrays and primitives
|
|
356
|
+
* are replaced wholesale. Plain objects are merged key-by-key so a partial
|
|
357
|
+
* override never erases sibling keys.
|
|
358
|
+
*/
|
|
359
|
+
declare function mergeLabels(base: IEditorLabels, override?: DeepPartial<IEditorLabels>): IEditorLabels;
|
|
360
|
+
|
|
89
361
|
interface FormEditorProps {
|
|
90
362
|
theme?: Record<string, unknown>;
|
|
91
363
|
dataSources?: Record<string, IDataSourceConnector>;
|
|
@@ -94,6 +366,12 @@ interface FormEditorProps {
|
|
|
94
366
|
formId?: string;
|
|
95
367
|
onChange?: (form: IFormDefinition) => void;
|
|
96
368
|
onSave?: () => void;
|
|
369
|
+
/**
|
|
370
|
+
* Localised labels for every visible string in the editor.
|
|
371
|
+
* Deep-merged with the French defaults — pass only the keys you want to
|
|
372
|
+
* override. Use {@link import('../i18n').enLabels} for English out of the box.
|
|
373
|
+
*/
|
|
374
|
+
labels?: DeepPartial<IEditorLabels>;
|
|
97
375
|
PreviewComponent?: ComponentType<{
|
|
98
376
|
formSchema: IFormDefinition;
|
|
99
377
|
theme?: Record<string, unknown>;
|
|
@@ -107,7 +385,7 @@ interface FormEditorProps {
|
|
|
107
385
|
/** Wrapper around the entire editor (e.g. DndContext) */
|
|
108
386
|
Wrapper?: ComponentType<any>;
|
|
109
387
|
}
|
|
110
|
-
declare function FormEditor({ theme, dataSources, adapter, initialForm, formId, onChange, onSave, PreviewComponent, ToolboxComponent, CanvasComponent, Wrapper, }: FormEditorProps): react_jsx_runtime.JSX.Element;
|
|
388
|
+
declare function FormEditor({ theme, dataSources, adapter, initialForm, formId, onChange, onSave, labels, PreviewComponent, ToolboxComponent, CanvasComponent, Wrapper, }: FormEditorProps): react_jsx_runtime.JSX.Element;
|
|
111
389
|
|
|
112
390
|
declare const useEditorStore: zustand.UseBoundStore<zustand.StoreApi<EditorStore>>;
|
|
113
391
|
|
|
@@ -138,6 +416,14 @@ interface PropertiesPanelProps {
|
|
|
138
416
|
}
|
|
139
417
|
declare function PropertiesPanel({ availableConnectors }: PropertiesPanelProps): react_jsx_runtime.JSX.Element;
|
|
140
418
|
|
|
419
|
+
interface RosterConditionContext {
|
|
420
|
+
/** Variables that belong to the same roster row (scope-restricted). */
|
|
421
|
+
variables: IRosterVariableRef[];
|
|
422
|
+
/** Code of the variable whose conditions are being edited. */
|
|
423
|
+
currentVariableCode: string;
|
|
424
|
+
/** Order of the variable whose conditions are being edited. */
|
|
425
|
+
currentVariableOrder: number;
|
|
426
|
+
}
|
|
141
427
|
interface ConditionBuilderProps {
|
|
142
428
|
conditions: IConditionRule[];
|
|
143
429
|
onChange: (conditions: IConditionRule[]) => void;
|
|
@@ -146,8 +432,13 @@ interface ConditionBuilderProps {
|
|
|
146
432
|
code: string;
|
|
147
433
|
name: string;
|
|
148
434
|
}>;
|
|
435
|
+
/**
|
|
436
|
+
* When set, conditions are validated against the roster scope using
|
|
437
|
+
* RosterConditionEngine. Scope errors are displayed under each rule.
|
|
438
|
+
*/
|
|
439
|
+
rosterContext?: RosterConditionContext;
|
|
149
440
|
}
|
|
150
|
-
declare function ConditionBuilder({ conditions, onChange, availableVariables }: ConditionBuilderProps): react_jsx_runtime.JSX.Element;
|
|
441
|
+
declare function ConditionBuilder({ conditions, onChange, availableVariables, rosterContext, }: ConditionBuilderProps): react_jsx_runtime.JSX.Element;
|
|
151
442
|
|
|
152
443
|
interface DataSourceSelectorProps {
|
|
153
444
|
/** Currently selected connector ID */
|
|
@@ -168,4 +459,4 @@ interface DataSourceSelectorProps {
|
|
|
168
459
|
}
|
|
169
460
|
declare function DataSourceSelector({ dataSourceId, dependencies, availableConnectors, availableVariables, onConnectorChange, onDependenciesChange, }: DataSourceSelectorProps): react_jsx_runtime.JSX.Element;
|
|
170
461
|
|
|
171
|
-
export { CanvasSimple as Canvas, ConditionBuilder, type ConditionBuilderProps, DataSourceSelector, type DataSourceSelectorProps, type EditorActions, type EditorSelection, type EditorState, type EditorStore, EditorToolbar, type EditorView, FormEditor, type FormEditorProps, type HistoryEntry, type IEditorAdapter, PropertiesPanel, ToolboxSimple as Toolbox, useEditorStore };
|
|
462
|
+
export { CanvasSimple as Canvas, ConditionBuilder, type ConditionBuilderProps, DataSourceSelector, type DataSourceSelectorProps, type DeepPartial, type EditorActions, EditorLabelsProvider, type EditorSelection, type EditorState, type EditorStore, EditorToolbar, type EditorView, FormEditor, type FormEditorProps, type HistoryEntry, type IEditorAdapter, type IEditorLabels, PropertiesPanel, ToolboxSimple as Toolbox, frLabels as defaultLabels, enLabels, frLabels, mergeLabels, useEditorStore, useLabels };
|