@form-engine-ts/react 1.1.0 → 2.1.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/dist/index.d.cts CHANGED
@@ -1,6 +1,82 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ComponentType } from 'react';
3
- import { FormSchema, TranslationAdapter, AsyncTranslationAdapter, FormField, FormValue, ValidationIssue, FormValues, AnswerValidationResult, FieldType } from '@form-engine-ts/core';
3
+ import { QuestionType, FormField, ChoiceOption, FormPage, FormPolicy, FormSchema, DisplayCondition, JsonValue, SchemaIssue, TranslationAdapter, AsyncTranslationAdapter, PopulateTranslationOptions, TranslationReport, ValidationError, FormValue, ValidationIssue, FormValues, AnswerValidationResult, FieldType } from '@form-engine-ts/core';
4
+
5
+ /** @deprecated Import FormPolicy from @form-engine-ts/core instead. */
6
+ type BuilderPolicy = FormPolicy;
7
+ type BuilderIdKind = "field" | "option" | "page";
8
+ interface BuilderFactories {
9
+ readonly createField?: (type: QuestionType, id: string) => FormField;
10
+ readonly createOption?: (field: FormField, id: string) => ChoiceOption;
11
+ readonly createPage?: (id: string, questionIds: string[]) => FormPage;
12
+ }
13
+ interface BuilderTextTarget {
14
+ readonly kind: "form" | "page" | "field" | "option";
15
+ readonly id?: string;
16
+ }
17
+ interface FormBuilderOptions {
18
+ readonly schema: FormSchema;
19
+ readonly onChange: (schema: FormSchema) => void;
20
+ readonly policy?: FormPolicy;
21
+ readonly idFactory?: (kind: BuilderIdKind, existingIds: ReadonlySet<string>) => string;
22
+ readonly factories?: BuilderFactories;
23
+ }
24
+ type BuilderActionError = {
25
+ readonly type: "invalid_id";
26
+ readonly kind: BuilderIdKind;
27
+ readonly id: string;
28
+ } | {
29
+ readonly type: "max_fields_exceeded";
30
+ readonly max: number;
31
+ } | {
32
+ readonly type: "max_options_exceeded";
33
+ readonly max: number;
34
+ } | {
35
+ readonly type: "max_text_length_exceeded";
36
+ readonly max: number;
37
+ } | {
38
+ readonly type: "disallowed_field_type";
39
+ readonly fieldType: QuestionType;
40
+ } | {
41
+ readonly type: "node_not_found";
42
+ readonly kind: BuilderTextTarget["kind"];
43
+ readonly id: string;
44
+ } | {
45
+ readonly type: "invalid_operation";
46
+ readonly message: string;
47
+ };
48
+ type BuilderActionResult = {
49
+ readonly success: true;
50
+ } | {
51
+ readonly success: false;
52
+ readonly error: BuilderActionError;
53
+ };
54
+ interface FormBuilderResult {
55
+ readonly schema: FormSchema;
56
+ readonly addField: (type: QuestionType, pageId?: string) => BuilderActionResult;
57
+ readonly removeField: (fieldId: string) => BuilderActionResult;
58
+ readonly moveField: (fieldId: string, targetIndex: number) => BuilderActionResult;
59
+ readonly updateField: (fieldId: string, updater: (field: FormField) => FormField) => BuilderActionResult;
60
+ readonly changeFieldType: (fieldId: string, type: QuestionType) => BuilderActionResult;
61
+ readonly addOption: (fieldId: string) => BuilderActionResult;
62
+ readonly updateOption: (fieldId: string, optionId: string, updater: (option: ChoiceOption) => ChoiceOption) => BuilderActionResult;
63
+ readonly removeOption: (fieldId: string, optionId: string) => BuilderActionResult;
64
+ readonly moveOption: (fieldId: string, optionId: string, targetIndex: number) => BuilderActionResult;
65
+ readonly addPage: (questionId?: string) => BuilderActionResult;
66
+ readonly updatePage: (pageId: string, updater: (page: FormPage) => FormPage) => BuilderActionResult;
67
+ readonly removePage: (pageId: string) => BuilderActionResult;
68
+ readonly movePage: (pageId: string, targetIndex: number) => BuilderActionResult;
69
+ readonly assignFieldToPage: (fieldId: string, pageId: string | null) => BuilderActionResult;
70
+ readonly setDisplayCondition: (fieldId: string, condition?: DisplayCondition) => BuilderActionResult;
71
+ readonly setSourceText: (target: BuilderTextTarget, property: string, text: string) => BuilderActionResult;
72
+ readonly setLocaleTranslation: (locale: string, target: BuilderTextTarget, property: string, text: string, options?: {
73
+ readonly metadata?: Record<string, JsonValue>;
74
+ }) => BuilderActionResult;
75
+ readonly addLocale: (locale: string) => BuilderActionResult;
76
+ readonly setDefaultLocale: (locale: string) => BuilderActionResult;
77
+ readonly validationIssues: readonly SchemaIssue[];
78
+ }
79
+ declare function useFormBuilder({ schema, onChange, policy, idFactory, factories }: FormBuilderOptions): FormBuilderResult;
4
80
 
5
81
  interface FormBuilderProps {
6
82
  readonly schema: FormSchema;
@@ -8,8 +84,65 @@ interface FormBuilderProps {
8
84
  readonly locale?: string;
9
85
  readonly translator?: TranslationAdapter;
10
86
  readonly translationAdapter?: AsyncTranslationAdapter;
87
+ readonly translationOptions?: PopulateTranslationOptions;
88
+ readonly onTranslationReport?: (report: TranslationReport) => void;
89
+ readonly policy?: FormPolicy;
90
+ readonly idFactory?: (kind: "field" | "option" | "page", existingIds: ReadonlySet<string>) => string;
91
+ readonly factories?: BuilderFactories;
11
92
  }
12
- declare function FormBuilder({ schema, onChange, locale, translator, translationAdapter }: FormBuilderProps): react.JSX.Element;
93
+ declare function FormBuilder({ schema, onChange, locale, translator, translationAdapter, translationOptions, onTranslationReport, policy, idFactory, factories }: FormBuilderProps): react.JSX.Element;
94
+
95
+ type SubmitResult = {
96
+ readonly status: "invalid";
97
+ readonly issues: readonly ValidationError[];
98
+ } | {
99
+ readonly status: "cancelled";
100
+ } | {
101
+ readonly status: "success";
102
+ } | {
103
+ readonly status: "error";
104
+ readonly error: Error;
105
+ };
106
+ interface FormRendererSlots {
107
+ readonly renderHeader?: (props: {
108
+ readonly title: string;
109
+ readonly description?: string;
110
+ }) => ReactNode;
111
+ readonly renderPageHeader?: (props: {
112
+ readonly page: FormPage;
113
+ readonly pageIndex: number;
114
+ readonly totalPages: number;
115
+ }) => ReactNode;
116
+ readonly renderField?: (props: {
117
+ readonly question: FormField;
118
+ readonly value: unknown;
119
+ readonly onChange: (value: unknown) => void;
120
+ readonly error?: ValidationError;
121
+ }) => ReactNode;
122
+ readonly renderNavigation?: (props: {
123
+ readonly currentPage: number;
124
+ readonly totalPages: number;
125
+ readonly canPrev: boolean;
126
+ readonly canNext: boolean;
127
+ readonly onPrev: () => void;
128
+ readonly onNext: () => void;
129
+ }) => ReactNode;
130
+ readonly renderSubmitButton?: (props: {
131
+ readonly isSubmitting: boolean;
132
+ readonly onSubmit: () => void;
133
+ }) => ReactNode;
134
+ readonly renderValidationSummary?: (props: {
135
+ readonly issues: readonly ValidationError[];
136
+ }) => ReactNode;
137
+ readonly renderCompletion?: (props: {
138
+ readonly message: string;
139
+ }) => ReactNode;
140
+ readonly renderSubmitError?: (props: {
141
+ readonly error: Error;
142
+ readonly onRetry?: () => void;
143
+ }) => ReactNode;
144
+ }
145
+ type BeforeSubmit = (values: Readonly<Record<string, unknown>>) => "continue" | "cancel" | Promise<"continue" | "cancel">;
13
146
 
14
147
  type SubmitStatus = "idle" | "submitting" | "success" | "error";
15
148
  interface FormContextValue {
@@ -27,7 +160,7 @@ interface FormContextValue {
27
160
  readonly restoreValues: (values: FormValues) => void;
28
161
  readonly validatePage: (pageIndex: number) => AnswerValidationResult;
29
162
  readonly reset: () => void;
30
- readonly submit: () => Promise<boolean>;
163
+ readonly submit: (beforeSubmit?: BeforeSubmit) => Promise<SubmitResult>;
31
164
  readonly translate: (key: string, params?: Readonly<Record<string, string | number>>) => string;
32
165
  }
33
166
  interface FormProviderProps {
@@ -60,13 +193,25 @@ interface FieldComponentProps {
60
193
  readonly helpId: string;
61
194
  }
62
195
  type FieldComponents = Partial<Record<FieldType, ComponentType<FieldComponentProps>>>;
63
- interface FormRendererProps {
196
+ interface FormRendererPresentationProps {
64
197
  readonly components?: FieldComponents;
65
198
  readonly className?: string;
66
199
  readonly successMessageKey?: string;
67
200
  readonly errorMessageKey?: string;
68
201
  readonly autoSaveKey?: string;
202
+ readonly beforeSubmit?: BeforeSubmit;
203
+ readonly onDraftSave?: (draft: FormValues) => void;
204
+ readonly slots?: FormRendererSlots;
205
+ }
206
+ interface StandaloneFormRendererProps extends FormRendererPresentationProps {
207
+ readonly schema: FormSchema;
208
+ readonly locale?: string;
209
+ readonly translator?: TranslationAdapter;
210
+ readonly initialValues?: FormValues;
211
+ readonly resetOnSuccess?: boolean;
212
+ readonly onSubmit: (answers: FormValues) => Promise<void> | void;
69
213
  }
70
- declare function FormRenderer({ components, className, successMessageKey, errorMessageKey, autoSaveKey }: FormRendererProps): react.JSX.Element;
214
+ type FormRendererProps = FormRendererPresentationProps | StandaloneFormRendererProps;
215
+ declare function FormRenderer(props: FormRendererProps): react.JSX.Element;
71
216
 
72
- export { type FieldComponentProps, type FieldComponents, type FieldState, FormBuilder, type FormBuilderProps, type FormContextValue, FormProvider, type FormProviderProps, FormRenderer, type FormRendererProps, type SubmitStatus, useField, useForm };
217
+ export { type BeforeSubmit, type BuilderActionError, type BuilderActionResult, type BuilderFactories, type BuilderIdKind, type BuilderPolicy, type BuilderTextTarget, type FieldComponentProps, type FieldComponents, type FieldState, FormBuilder, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormContextValue, FormProvider, type FormProviderProps, FormRenderer, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type StandaloneFormRendererProps, type SubmitResult, type SubmitStatus, useField, useForm, useFormBuilder };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,82 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ComponentType } from 'react';
3
- import { FormSchema, TranslationAdapter, AsyncTranslationAdapter, FormField, FormValue, ValidationIssue, FormValues, AnswerValidationResult, FieldType } from '@form-engine-ts/core';
3
+ import { QuestionType, FormField, ChoiceOption, FormPage, FormPolicy, FormSchema, DisplayCondition, JsonValue, SchemaIssue, TranslationAdapter, AsyncTranslationAdapter, PopulateTranslationOptions, TranslationReport, ValidationError, FormValue, ValidationIssue, FormValues, AnswerValidationResult, FieldType } from '@form-engine-ts/core';
4
+
5
+ /** @deprecated Import FormPolicy from @form-engine-ts/core instead. */
6
+ type BuilderPolicy = FormPolicy;
7
+ type BuilderIdKind = "field" | "option" | "page";
8
+ interface BuilderFactories {
9
+ readonly createField?: (type: QuestionType, id: string) => FormField;
10
+ readonly createOption?: (field: FormField, id: string) => ChoiceOption;
11
+ readonly createPage?: (id: string, questionIds: string[]) => FormPage;
12
+ }
13
+ interface BuilderTextTarget {
14
+ readonly kind: "form" | "page" | "field" | "option";
15
+ readonly id?: string;
16
+ }
17
+ interface FormBuilderOptions {
18
+ readonly schema: FormSchema;
19
+ readonly onChange: (schema: FormSchema) => void;
20
+ readonly policy?: FormPolicy;
21
+ readonly idFactory?: (kind: BuilderIdKind, existingIds: ReadonlySet<string>) => string;
22
+ readonly factories?: BuilderFactories;
23
+ }
24
+ type BuilderActionError = {
25
+ readonly type: "invalid_id";
26
+ readonly kind: BuilderIdKind;
27
+ readonly id: string;
28
+ } | {
29
+ readonly type: "max_fields_exceeded";
30
+ readonly max: number;
31
+ } | {
32
+ readonly type: "max_options_exceeded";
33
+ readonly max: number;
34
+ } | {
35
+ readonly type: "max_text_length_exceeded";
36
+ readonly max: number;
37
+ } | {
38
+ readonly type: "disallowed_field_type";
39
+ readonly fieldType: QuestionType;
40
+ } | {
41
+ readonly type: "node_not_found";
42
+ readonly kind: BuilderTextTarget["kind"];
43
+ readonly id: string;
44
+ } | {
45
+ readonly type: "invalid_operation";
46
+ readonly message: string;
47
+ };
48
+ type BuilderActionResult = {
49
+ readonly success: true;
50
+ } | {
51
+ readonly success: false;
52
+ readonly error: BuilderActionError;
53
+ };
54
+ interface FormBuilderResult {
55
+ readonly schema: FormSchema;
56
+ readonly addField: (type: QuestionType, pageId?: string) => BuilderActionResult;
57
+ readonly removeField: (fieldId: string) => BuilderActionResult;
58
+ readonly moveField: (fieldId: string, targetIndex: number) => BuilderActionResult;
59
+ readonly updateField: (fieldId: string, updater: (field: FormField) => FormField) => BuilderActionResult;
60
+ readonly changeFieldType: (fieldId: string, type: QuestionType) => BuilderActionResult;
61
+ readonly addOption: (fieldId: string) => BuilderActionResult;
62
+ readonly updateOption: (fieldId: string, optionId: string, updater: (option: ChoiceOption) => ChoiceOption) => BuilderActionResult;
63
+ readonly removeOption: (fieldId: string, optionId: string) => BuilderActionResult;
64
+ readonly moveOption: (fieldId: string, optionId: string, targetIndex: number) => BuilderActionResult;
65
+ readonly addPage: (questionId?: string) => BuilderActionResult;
66
+ readonly updatePage: (pageId: string, updater: (page: FormPage) => FormPage) => BuilderActionResult;
67
+ readonly removePage: (pageId: string) => BuilderActionResult;
68
+ readonly movePage: (pageId: string, targetIndex: number) => BuilderActionResult;
69
+ readonly assignFieldToPage: (fieldId: string, pageId: string | null) => BuilderActionResult;
70
+ readonly setDisplayCondition: (fieldId: string, condition?: DisplayCondition) => BuilderActionResult;
71
+ readonly setSourceText: (target: BuilderTextTarget, property: string, text: string) => BuilderActionResult;
72
+ readonly setLocaleTranslation: (locale: string, target: BuilderTextTarget, property: string, text: string, options?: {
73
+ readonly metadata?: Record<string, JsonValue>;
74
+ }) => BuilderActionResult;
75
+ readonly addLocale: (locale: string) => BuilderActionResult;
76
+ readonly setDefaultLocale: (locale: string) => BuilderActionResult;
77
+ readonly validationIssues: readonly SchemaIssue[];
78
+ }
79
+ declare function useFormBuilder({ schema, onChange, policy, idFactory, factories }: FormBuilderOptions): FormBuilderResult;
4
80
 
5
81
  interface FormBuilderProps {
6
82
  readonly schema: FormSchema;
@@ -8,8 +84,65 @@ interface FormBuilderProps {
8
84
  readonly locale?: string;
9
85
  readonly translator?: TranslationAdapter;
10
86
  readonly translationAdapter?: AsyncTranslationAdapter;
87
+ readonly translationOptions?: PopulateTranslationOptions;
88
+ readonly onTranslationReport?: (report: TranslationReport) => void;
89
+ readonly policy?: FormPolicy;
90
+ readonly idFactory?: (kind: "field" | "option" | "page", existingIds: ReadonlySet<string>) => string;
91
+ readonly factories?: BuilderFactories;
11
92
  }
12
- declare function FormBuilder({ schema, onChange, locale, translator, translationAdapter }: FormBuilderProps): react.JSX.Element;
93
+ declare function FormBuilder({ schema, onChange, locale, translator, translationAdapter, translationOptions, onTranslationReport, policy, idFactory, factories }: FormBuilderProps): react.JSX.Element;
94
+
95
+ type SubmitResult = {
96
+ readonly status: "invalid";
97
+ readonly issues: readonly ValidationError[];
98
+ } | {
99
+ readonly status: "cancelled";
100
+ } | {
101
+ readonly status: "success";
102
+ } | {
103
+ readonly status: "error";
104
+ readonly error: Error;
105
+ };
106
+ interface FormRendererSlots {
107
+ readonly renderHeader?: (props: {
108
+ readonly title: string;
109
+ readonly description?: string;
110
+ }) => ReactNode;
111
+ readonly renderPageHeader?: (props: {
112
+ readonly page: FormPage;
113
+ readonly pageIndex: number;
114
+ readonly totalPages: number;
115
+ }) => ReactNode;
116
+ readonly renderField?: (props: {
117
+ readonly question: FormField;
118
+ readonly value: unknown;
119
+ readonly onChange: (value: unknown) => void;
120
+ readonly error?: ValidationError;
121
+ }) => ReactNode;
122
+ readonly renderNavigation?: (props: {
123
+ readonly currentPage: number;
124
+ readonly totalPages: number;
125
+ readonly canPrev: boolean;
126
+ readonly canNext: boolean;
127
+ readonly onPrev: () => void;
128
+ readonly onNext: () => void;
129
+ }) => ReactNode;
130
+ readonly renderSubmitButton?: (props: {
131
+ readonly isSubmitting: boolean;
132
+ readonly onSubmit: () => void;
133
+ }) => ReactNode;
134
+ readonly renderValidationSummary?: (props: {
135
+ readonly issues: readonly ValidationError[];
136
+ }) => ReactNode;
137
+ readonly renderCompletion?: (props: {
138
+ readonly message: string;
139
+ }) => ReactNode;
140
+ readonly renderSubmitError?: (props: {
141
+ readonly error: Error;
142
+ readonly onRetry?: () => void;
143
+ }) => ReactNode;
144
+ }
145
+ type BeforeSubmit = (values: Readonly<Record<string, unknown>>) => "continue" | "cancel" | Promise<"continue" | "cancel">;
13
146
 
14
147
  type SubmitStatus = "idle" | "submitting" | "success" | "error";
15
148
  interface FormContextValue {
@@ -27,7 +160,7 @@ interface FormContextValue {
27
160
  readonly restoreValues: (values: FormValues) => void;
28
161
  readonly validatePage: (pageIndex: number) => AnswerValidationResult;
29
162
  readonly reset: () => void;
30
- readonly submit: () => Promise<boolean>;
163
+ readonly submit: (beforeSubmit?: BeforeSubmit) => Promise<SubmitResult>;
31
164
  readonly translate: (key: string, params?: Readonly<Record<string, string | number>>) => string;
32
165
  }
33
166
  interface FormProviderProps {
@@ -60,13 +193,25 @@ interface FieldComponentProps {
60
193
  readonly helpId: string;
61
194
  }
62
195
  type FieldComponents = Partial<Record<FieldType, ComponentType<FieldComponentProps>>>;
63
- interface FormRendererProps {
196
+ interface FormRendererPresentationProps {
64
197
  readonly components?: FieldComponents;
65
198
  readonly className?: string;
66
199
  readonly successMessageKey?: string;
67
200
  readonly errorMessageKey?: string;
68
201
  readonly autoSaveKey?: string;
202
+ readonly beforeSubmit?: BeforeSubmit;
203
+ readonly onDraftSave?: (draft: FormValues) => void;
204
+ readonly slots?: FormRendererSlots;
205
+ }
206
+ interface StandaloneFormRendererProps extends FormRendererPresentationProps {
207
+ readonly schema: FormSchema;
208
+ readonly locale?: string;
209
+ readonly translator?: TranslationAdapter;
210
+ readonly initialValues?: FormValues;
211
+ readonly resetOnSuccess?: boolean;
212
+ readonly onSubmit: (answers: FormValues) => Promise<void> | void;
69
213
  }
70
- declare function FormRenderer({ components, className, successMessageKey, errorMessageKey, autoSaveKey }: FormRendererProps): react.JSX.Element;
214
+ type FormRendererProps = FormRendererPresentationProps | StandaloneFormRendererProps;
215
+ declare function FormRenderer(props: FormRendererProps): react.JSX.Element;
71
216
 
72
- export { type FieldComponentProps, type FieldComponents, type FieldState, FormBuilder, type FormBuilderProps, type FormContextValue, FormProvider, type FormProviderProps, FormRenderer, type FormRendererProps, type SubmitStatus, useField, useForm };
217
+ export { type BeforeSubmit, type BuilderActionError, type BuilderActionResult, type BuilderFactories, type BuilderIdKind, type BuilderPolicy, type BuilderTextTarget, type FieldComponentProps, type FieldComponents, type FieldState, FormBuilder, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormContextValue, FormProvider, type FormProviderProps, FormRenderer, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type StandaloneFormRendererProps, type SubmitResult, type SubmitStatus, useField, useForm, useFormBuilder };