@form-engine-ts/react 3.2.0 → 4.0.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 +4 -1
- package/dist/index.cjs +60 -21
- package/dist/index.d.cts +21 -10
- package/dist/index.d.ts +21 -10
- package/dist/index.js +58 -21
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -96,11 +96,14 @@ When either is enabled, the builder omits its `form-engine-builder` and `feb-*`
|
|
|
96
96
|
and `Select` components receive the field `label` and accessibility attributes and are responsible for rendering their
|
|
97
97
|
own labels. Builder action icons can be supplied with `renderIcon`, which resolves `actionType` values such as
|
|
98
98
|
`moveUp`, `moveDown`, `delete`, and `add`. `renderFieldTypeIcon` supplies icons for field-type selectors. Select
|
|
99
|
-
options may be strings or `BuilderSelectOption` objects with `icon`, `description`, `
|
|
99
|
+
options may be strings or `BuilderSelectOption` objects with `icon`, `description`, `group`, `groupLabel`, `kind`, and
|
|
100
|
+
`metadata`; custom
|
|
100
101
|
`renderOption` and `renderValue` functions can control their presentation. `BUILDER_TRANSLATION_KEYS` exposes the
|
|
101
102
|
canonical typed builder translation keys while legacy catalog aliases remain supported.
|
|
102
103
|
|
|
103
104
|
The `fieldEditor` slot can expose only the type selector or header through `fieldTypeSelect` and `fieldEditorHeader`:
|
|
105
|
+
The `fieldTypeSelect` slot receives the resolved `id`, `name`, `label`, `options`, and accessibility attributes in addition
|
|
106
|
+
to `currentType`, `allowedTypes`, and `onChangeType`.
|
|
104
107
|
|
|
105
108
|
```tsx
|
|
106
109
|
<FormBuilder
|
package/dist/index.cjs
CHANGED
|
@@ -28,7 +28,9 @@ __export(index_exports, {
|
|
|
28
28
|
FormSubmissionError: () => FormSubmissionError,
|
|
29
29
|
createLocalStorageSubmissionAttemptStore: () => createLocalStorageSubmissionAttemptStore,
|
|
30
30
|
createLocalStorageSubmissionReceiptStore: () => createLocalStorageSubmissionReceiptStore,
|
|
31
|
+
isTranslationUnresolved: () => isTranslationUnresolved,
|
|
31
32
|
resolveInitialFieldType: () => resolveInitialFieldType,
|
|
33
|
+
resolveTranslation: () => resolveTranslation,
|
|
32
34
|
submissionReceiptQueryKey: () => submissionReceiptQueryKey,
|
|
33
35
|
useField: () => useField,
|
|
34
36
|
useForm: () => useForm,
|
|
@@ -802,6 +804,41 @@ var BUILDER_TRANSLATION_ALIASES = {
|
|
|
802
804
|
"builder.fields.typeSelect": "builder.fieldType.select",
|
|
803
805
|
"builder.fields.typeMultiSelect": "builder.fieldType.multi-select"
|
|
804
806
|
};
|
|
807
|
+
function isTranslationUnresolved(result, key, aliases = []) {
|
|
808
|
+
if (result === void 0 || result === null || result === "") return true;
|
|
809
|
+
if (typeof result !== "string") return false;
|
|
810
|
+
if (result === key || aliases.includes(result)) return true;
|
|
811
|
+
return result.endsWith(key) || aliases.some((alias) => result.endsWith(alias));
|
|
812
|
+
}
|
|
813
|
+
function isResolvedAdapterResult(result, key, aliases) {
|
|
814
|
+
return typeof result === "string" && result.startsWith("translated:") ? true : !isTranslationUnresolved(result, key, aliases);
|
|
815
|
+
}
|
|
816
|
+
function formatTemplate(template, params) {
|
|
817
|
+
return template.replace(
|
|
818
|
+
/\{\{(\w+)\}\}/g,
|
|
819
|
+
(token, name) => Object.hasOwn(params, name) ? String(params[name]) : token
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
function resolveTranslation(key, aliases, adapter, defaultCatalog, params = {}, locale = "") {
|
|
823
|
+
const adapterParams = {};
|
|
824
|
+
for (const [name, value] of Object.entries(params)) {
|
|
825
|
+
if (typeof value === "string" || typeof value === "number") adapterParams[name] = value;
|
|
826
|
+
}
|
|
827
|
+
const translate = (candidate) => adapter?.translate(candidate, locale, adapterParams);
|
|
828
|
+
const translated = translate(key);
|
|
829
|
+
if (isResolvedAdapterResult(translated, key, aliases)) return translated;
|
|
830
|
+
for (const alias of aliases) {
|
|
831
|
+
const aliased = translate(alias);
|
|
832
|
+
if (isResolvedAdapterResult(aliased, alias, aliases)) return aliased;
|
|
833
|
+
}
|
|
834
|
+
const catalogValue = defaultCatalog?.[key];
|
|
835
|
+
if (catalogValue !== void 0) return formatTemplate(catalogValue, params);
|
|
836
|
+
for (const alias of aliases) {
|
|
837
|
+
const aliasValue = defaultCatalog?.[alias];
|
|
838
|
+
if (aliasValue !== void 0) return formatTemplate(aliasValue, params);
|
|
839
|
+
}
|
|
840
|
+
return key;
|
|
841
|
+
}
|
|
805
842
|
|
|
806
843
|
// src/builder.tsx
|
|
807
844
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -1334,6 +1371,18 @@ var BUILDER_DEFAULTS = {
|
|
|
1334
1371
|
"builder.fields.typeMultiSelect": "Multi-select",
|
|
1335
1372
|
"builder.fields.typeCheckbox": "Checkbox",
|
|
1336
1373
|
"builder.fields.typeRadio": "Radio",
|
|
1374
|
+
"builder.fieldCategory.text": "Text",
|
|
1375
|
+
"builder.fieldCategory.choice": "Choice",
|
|
1376
|
+
"builder.fieldCategory.number": "Number",
|
|
1377
|
+
"builder.fieldCategory.advanced": "Advanced",
|
|
1378
|
+
"builder.fieldTypeDescription.text": "A single-line text answer",
|
|
1379
|
+
"builder.fieldTypeDescription.textarea": "A long-form text answer",
|
|
1380
|
+
"builder.fieldTypeDescription.number": "A numeric answer",
|
|
1381
|
+
"builder.fieldTypeDescription.rating": "A rating scale answer",
|
|
1382
|
+
"builder.fieldTypeDescription.radio": "A single-choice answer",
|
|
1383
|
+
"builder.fieldTypeDescription.checkbox": "A yes/no answer",
|
|
1384
|
+
"builder.fieldTypeDescription.select": "A dropdown choice",
|
|
1385
|
+
"builder.fieldTypeDescription.multi-select": "Multiple choices",
|
|
1337
1386
|
"builder.actions.addField": "Add question",
|
|
1338
1387
|
"builder.fieldType.text": "Text",
|
|
1339
1388
|
"builder.fieldType.textarea": "Textarea",
|
|
@@ -1348,12 +1397,6 @@ var BUILDER_DEFAULTS = {
|
|
|
1348
1397
|
"builder.operator.contains": "contains",
|
|
1349
1398
|
"builder.operator.not_empty": "is not empty"
|
|
1350
1399
|
};
|
|
1351
|
-
function interpolate(template, params) {
|
|
1352
|
-
return template.replace(
|
|
1353
|
-
/\{\{(\w+)\}\}/g,
|
|
1354
|
-
(token, name) => Object.hasOwn(params, name) ? String(params[name]) : token
|
|
1355
|
-
);
|
|
1356
|
-
}
|
|
1357
1400
|
function BuilderSectionGroup({ children }) {
|
|
1358
1401
|
return children;
|
|
1359
1402
|
}
|
|
@@ -1558,20 +1601,14 @@ function FormBuilder({
|
|
|
1558
1601
|
const [isTranslating, setIsTranslating] = (0, import_react2.useState)(false);
|
|
1559
1602
|
const [translationError, setTranslationError] = (0, import_react2.useState)(null);
|
|
1560
1603
|
const [translationReport, setTranslationReport] = (0, import_react2.useState)();
|
|
1561
|
-
const translate = (key, params = {}) =>
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
if (alias !== void 0) {
|
|
1570
|
-
const aliased = translator?.translate(alias, locale, translatorParams);
|
|
1571
|
-
if (aliased !== void 0 && aliased !== alias) return aliased;
|
|
1572
|
-
}
|
|
1573
|
-
return translated === void 0 ? interpolate(BUILDER_DEFAULTS[key] ?? key, params) : translated;
|
|
1574
|
-
};
|
|
1604
|
+
const translate = (key, params = {}) => resolveTranslation(
|
|
1605
|
+
key,
|
|
1606
|
+
BUILDER_TRANSLATION_ALIASES[key] === void 0 ? [] : [BUILDER_TRANSLATION_ALIASES[key]],
|
|
1607
|
+
translator,
|
|
1608
|
+
BUILDER_DEFAULTS,
|
|
1609
|
+
params,
|
|
1610
|
+
locale
|
|
1611
|
+
);
|
|
1575
1612
|
const pagesEnabled = features?.pages ?? true;
|
|
1576
1613
|
const localizationEnabled = features?.localization ?? true;
|
|
1577
1614
|
const conditionsEnabled = features?.conditions ?? true;
|
|
@@ -2852,7 +2889,7 @@ function FormProvider({
|
|
|
2852
2889
|
[initialValues, locale, onSubmit, resetOnSuccess, validSchema, values]
|
|
2853
2890
|
);
|
|
2854
2891
|
const translate = (0, import_react3.useCallback)(
|
|
2855
|
-
(key, params) => translator.translate(key, locale, params),
|
|
2892
|
+
(key, params) => translator.translate(key, locale, params) ?? key,
|
|
2856
2893
|
[locale, translator]
|
|
2857
2894
|
);
|
|
2858
2895
|
const contextValue = (0, import_react3.useMemo)(
|
|
@@ -3963,7 +4000,9 @@ function FormRenderer(props) {
|
|
|
3963
4000
|
FormSubmissionError,
|
|
3964
4001
|
createLocalStorageSubmissionAttemptStore,
|
|
3965
4002
|
createLocalStorageSubmissionReceiptStore,
|
|
4003
|
+
isTranslationUnresolved,
|
|
3966
4004
|
resolveInitialFieldType,
|
|
4005
|
+
resolveTranslation,
|
|
3967
4006
|
submissionReceiptQueryKey,
|
|
3968
4007
|
useField,
|
|
3969
4008
|
useForm,
|
package/dist/index.d.cts
CHANGED
|
@@ -187,19 +187,19 @@ interface BuilderSelectOption<T extends string = string> {
|
|
|
187
187
|
readonly icon?: ReactNode;
|
|
188
188
|
readonly description?: string;
|
|
189
189
|
readonly disabled?: boolean;
|
|
190
|
+
readonly group?: string;
|
|
191
|
+
readonly groupLabel?: string;
|
|
190
192
|
readonly kind?: string;
|
|
191
193
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
192
194
|
}
|
|
193
|
-
interface SelectComponentProps extends InputComponentProps {
|
|
194
|
-
readonly
|
|
195
|
-
readonly
|
|
196
|
-
readonly
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
readonly options: readonly BuilderSelectOption[];
|
|
200
|
-
readonly renderOption?: (option: BuilderSelectOption) => ReactNode;
|
|
201
|
-
readonly renderValue?: (option: BuilderSelectOption | undefined) => ReactNode;
|
|
195
|
+
interface SelectComponentProps<T extends string = string> extends Omit<InputComponentProps, "value" | "onChange"> {
|
|
196
|
+
readonly value: T;
|
|
197
|
+
readonly onChange: (value: T) => void;
|
|
198
|
+
readonly options: readonly (T | BuilderSelectOption<T>)[];
|
|
199
|
+
readonly renderOption?: (option: BuilderSelectOption<T>) => ReactNode;
|
|
200
|
+
readonly renderValue?: (option: BuilderSelectOption<T> | undefined) => ReactNode;
|
|
202
201
|
}
|
|
202
|
+
type BuilderSelectProps<T extends string = string> = SelectComponentProps<T>;
|
|
203
203
|
interface BuilderCheckboxProps extends ComponentBaseProps {
|
|
204
204
|
readonly name?: string;
|
|
205
205
|
readonly required?: boolean;
|
|
@@ -281,11 +281,20 @@ interface BuilderFieldEditorSlotProps extends BuilderSlotBaseProps {
|
|
|
281
281
|
readonly slots?: Pick<FormBuilderSlots, "fieldTypeSelect" | "fieldEditorHeader">;
|
|
282
282
|
}
|
|
283
283
|
interface FieldTypeSelectSlotProps {
|
|
284
|
+
readonly id?: string;
|
|
285
|
+
readonly name?: string;
|
|
286
|
+
readonly label?: string;
|
|
284
287
|
readonly currentType: QuestionType;
|
|
285
288
|
readonly allowedTypes: readonly QuestionType[];
|
|
289
|
+
readonly options: readonly BuilderSelectOption<QuestionType>[];
|
|
286
290
|
readonly onChangeType: (nextType: QuestionType) => void;
|
|
287
291
|
readonly disabled?: boolean;
|
|
288
292
|
readonly readOnly?: boolean;
|
|
293
|
+
readonly required?: boolean;
|
|
294
|
+
readonly error?: boolean;
|
|
295
|
+
readonly helperText?: string;
|
|
296
|
+
readonly "aria-describedby"?: string;
|
|
297
|
+
readonly "aria-labelledby"?: string;
|
|
289
298
|
readonly renderIcon?: (type: QuestionType) => ReactNode;
|
|
290
299
|
}
|
|
291
300
|
interface FieldEditorHeaderSlotProps {
|
|
@@ -601,6 +610,8 @@ declare const BUILDER_TRANSLATION_KEYS: {
|
|
|
601
610
|
type BuilderTranslationKey = (typeof BUILDER_TRANSLATION_KEYS)[keyof typeof BUILDER_TRANSLATION_KEYS];
|
|
602
611
|
/** Legacy keys are checked when an older catalog does not contain a canonical key. */
|
|
603
612
|
declare const BUILDER_TRANSLATION_ALIASES: Readonly<Record<string, string>>;
|
|
613
|
+
declare function isTranslationUnresolved(result: unknown, key: string, aliases?: readonly string[]): boolean;
|
|
614
|
+
declare function resolveTranslation(key: string, aliases: readonly string[], adapter?: TranslationAdapter, defaultCatalog?: Readonly<Record<string, string>>, params?: Readonly<Record<string, unknown>>, locale?: string): string;
|
|
604
615
|
|
|
605
616
|
interface FieldComponentProps {
|
|
606
617
|
readonly field: FormField;
|
|
@@ -648,4 +659,4 @@ interface StandaloneFormRendererProps extends FormRendererPresentationProps {
|
|
|
648
659
|
type FormRendererProps = FormRendererPresentationProps | StandaloneFormRendererProps;
|
|
649
660
|
declare function FormRenderer(props: FormRendererProps): react.JSX.Element;
|
|
650
661
|
|
|
651
|
-
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ComponentBaseProps, type FieldComponentProps, type FieldComponents, type FieldEditorHeaderSlotProps, type FieldState, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormCompletionSlotProps, type FormContextValue, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type UseSubmissionReceiptsResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, resolveInitialFieldType, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useSubmissionReceipts };
|
|
662
|
+
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ComponentBaseProps, type FieldComponentProps, type FieldComponents, type FieldEditorHeaderSlotProps, type FieldState, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormCompletionSlotProps, type FormContextValue, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type UseSubmissionReceiptsResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useSubmissionReceipts };
|
package/dist/index.d.ts
CHANGED
|
@@ -187,19 +187,19 @@ interface BuilderSelectOption<T extends string = string> {
|
|
|
187
187
|
readonly icon?: ReactNode;
|
|
188
188
|
readonly description?: string;
|
|
189
189
|
readonly disabled?: boolean;
|
|
190
|
+
readonly group?: string;
|
|
191
|
+
readonly groupLabel?: string;
|
|
190
192
|
readonly kind?: string;
|
|
191
193
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
192
194
|
}
|
|
193
|
-
interface SelectComponentProps extends InputComponentProps {
|
|
194
|
-
readonly
|
|
195
|
-
readonly
|
|
196
|
-
readonly
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
readonly options: readonly BuilderSelectOption[];
|
|
200
|
-
readonly renderOption?: (option: BuilderSelectOption) => ReactNode;
|
|
201
|
-
readonly renderValue?: (option: BuilderSelectOption | undefined) => ReactNode;
|
|
195
|
+
interface SelectComponentProps<T extends string = string> extends Omit<InputComponentProps, "value" | "onChange"> {
|
|
196
|
+
readonly value: T;
|
|
197
|
+
readonly onChange: (value: T) => void;
|
|
198
|
+
readonly options: readonly (T | BuilderSelectOption<T>)[];
|
|
199
|
+
readonly renderOption?: (option: BuilderSelectOption<T>) => ReactNode;
|
|
200
|
+
readonly renderValue?: (option: BuilderSelectOption<T> | undefined) => ReactNode;
|
|
202
201
|
}
|
|
202
|
+
type BuilderSelectProps<T extends string = string> = SelectComponentProps<T>;
|
|
203
203
|
interface BuilderCheckboxProps extends ComponentBaseProps {
|
|
204
204
|
readonly name?: string;
|
|
205
205
|
readonly required?: boolean;
|
|
@@ -281,11 +281,20 @@ interface BuilderFieldEditorSlotProps extends BuilderSlotBaseProps {
|
|
|
281
281
|
readonly slots?: Pick<FormBuilderSlots, "fieldTypeSelect" | "fieldEditorHeader">;
|
|
282
282
|
}
|
|
283
283
|
interface FieldTypeSelectSlotProps {
|
|
284
|
+
readonly id?: string;
|
|
285
|
+
readonly name?: string;
|
|
286
|
+
readonly label?: string;
|
|
284
287
|
readonly currentType: QuestionType;
|
|
285
288
|
readonly allowedTypes: readonly QuestionType[];
|
|
289
|
+
readonly options: readonly BuilderSelectOption<QuestionType>[];
|
|
286
290
|
readonly onChangeType: (nextType: QuestionType) => void;
|
|
287
291
|
readonly disabled?: boolean;
|
|
288
292
|
readonly readOnly?: boolean;
|
|
293
|
+
readonly required?: boolean;
|
|
294
|
+
readonly error?: boolean;
|
|
295
|
+
readonly helperText?: string;
|
|
296
|
+
readonly "aria-describedby"?: string;
|
|
297
|
+
readonly "aria-labelledby"?: string;
|
|
289
298
|
readonly renderIcon?: (type: QuestionType) => ReactNode;
|
|
290
299
|
}
|
|
291
300
|
interface FieldEditorHeaderSlotProps {
|
|
@@ -601,6 +610,8 @@ declare const BUILDER_TRANSLATION_KEYS: {
|
|
|
601
610
|
type BuilderTranslationKey = (typeof BUILDER_TRANSLATION_KEYS)[keyof typeof BUILDER_TRANSLATION_KEYS];
|
|
602
611
|
/** Legacy keys are checked when an older catalog does not contain a canonical key. */
|
|
603
612
|
declare const BUILDER_TRANSLATION_ALIASES: Readonly<Record<string, string>>;
|
|
613
|
+
declare function isTranslationUnresolved(result: unknown, key: string, aliases?: readonly string[]): boolean;
|
|
614
|
+
declare function resolveTranslation(key: string, aliases: readonly string[], adapter?: TranslationAdapter, defaultCatalog?: Readonly<Record<string, string>>, params?: Readonly<Record<string, unknown>>, locale?: string): string;
|
|
604
615
|
|
|
605
616
|
interface FieldComponentProps {
|
|
606
617
|
readonly field: FormField;
|
|
@@ -648,4 +659,4 @@ interface StandaloneFormRendererProps extends FormRendererPresentationProps {
|
|
|
648
659
|
type FormRendererProps = FormRendererPresentationProps | StandaloneFormRendererProps;
|
|
649
660
|
declare function FormRenderer(props: FormRendererProps): react.JSX.Element;
|
|
650
661
|
|
|
651
|
-
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ComponentBaseProps, type FieldComponentProps, type FieldComponents, type FieldEditorHeaderSlotProps, type FieldState, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormCompletionSlotProps, type FormContextValue, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type UseSubmissionReceiptsResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, resolveInitialFieldType, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useSubmissionReceipts };
|
|
662
|
+
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ComponentBaseProps, type FieldComponentProps, type FieldComponents, type FieldEditorHeaderSlotProps, type FieldState, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormCompletionSlotProps, type FormContextValue, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type UseSubmissionReceiptsResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useSubmissionReceipts };
|
package/dist/index.js
CHANGED
|
@@ -770,6 +770,41 @@ var BUILDER_TRANSLATION_ALIASES = {
|
|
|
770
770
|
"builder.fields.typeSelect": "builder.fieldType.select",
|
|
771
771
|
"builder.fields.typeMultiSelect": "builder.fieldType.multi-select"
|
|
772
772
|
};
|
|
773
|
+
function isTranslationUnresolved(result, key, aliases = []) {
|
|
774
|
+
if (result === void 0 || result === null || result === "") return true;
|
|
775
|
+
if (typeof result !== "string") return false;
|
|
776
|
+
if (result === key || aliases.includes(result)) return true;
|
|
777
|
+
return result.endsWith(key) || aliases.some((alias) => result.endsWith(alias));
|
|
778
|
+
}
|
|
779
|
+
function isResolvedAdapterResult(result, key, aliases) {
|
|
780
|
+
return typeof result === "string" && result.startsWith("translated:") ? true : !isTranslationUnresolved(result, key, aliases);
|
|
781
|
+
}
|
|
782
|
+
function formatTemplate(template, params) {
|
|
783
|
+
return template.replace(
|
|
784
|
+
/\{\{(\w+)\}\}/g,
|
|
785
|
+
(token, name) => Object.hasOwn(params, name) ? String(params[name]) : token
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
function resolveTranslation(key, aliases, adapter, defaultCatalog, params = {}, locale = "") {
|
|
789
|
+
const adapterParams = {};
|
|
790
|
+
for (const [name, value] of Object.entries(params)) {
|
|
791
|
+
if (typeof value === "string" || typeof value === "number") adapterParams[name] = value;
|
|
792
|
+
}
|
|
793
|
+
const translate = (candidate) => adapter?.translate(candidate, locale, adapterParams);
|
|
794
|
+
const translated = translate(key);
|
|
795
|
+
if (isResolvedAdapterResult(translated, key, aliases)) return translated;
|
|
796
|
+
for (const alias of aliases) {
|
|
797
|
+
const aliased = translate(alias);
|
|
798
|
+
if (isResolvedAdapterResult(aliased, alias, aliases)) return aliased;
|
|
799
|
+
}
|
|
800
|
+
const catalogValue = defaultCatalog?.[key];
|
|
801
|
+
if (catalogValue !== void 0) return formatTemplate(catalogValue, params);
|
|
802
|
+
for (const alias of aliases) {
|
|
803
|
+
const aliasValue = defaultCatalog?.[alias];
|
|
804
|
+
if (aliasValue !== void 0) return formatTemplate(aliasValue, params);
|
|
805
|
+
}
|
|
806
|
+
return key;
|
|
807
|
+
}
|
|
773
808
|
|
|
774
809
|
// src/builder.tsx
|
|
775
810
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1302,6 +1337,18 @@ var BUILDER_DEFAULTS = {
|
|
|
1302
1337
|
"builder.fields.typeMultiSelect": "Multi-select",
|
|
1303
1338
|
"builder.fields.typeCheckbox": "Checkbox",
|
|
1304
1339
|
"builder.fields.typeRadio": "Radio",
|
|
1340
|
+
"builder.fieldCategory.text": "Text",
|
|
1341
|
+
"builder.fieldCategory.choice": "Choice",
|
|
1342
|
+
"builder.fieldCategory.number": "Number",
|
|
1343
|
+
"builder.fieldCategory.advanced": "Advanced",
|
|
1344
|
+
"builder.fieldTypeDescription.text": "A single-line text answer",
|
|
1345
|
+
"builder.fieldTypeDescription.textarea": "A long-form text answer",
|
|
1346
|
+
"builder.fieldTypeDescription.number": "A numeric answer",
|
|
1347
|
+
"builder.fieldTypeDescription.rating": "A rating scale answer",
|
|
1348
|
+
"builder.fieldTypeDescription.radio": "A single-choice answer",
|
|
1349
|
+
"builder.fieldTypeDescription.checkbox": "A yes/no answer",
|
|
1350
|
+
"builder.fieldTypeDescription.select": "A dropdown choice",
|
|
1351
|
+
"builder.fieldTypeDescription.multi-select": "Multiple choices",
|
|
1305
1352
|
"builder.actions.addField": "Add question",
|
|
1306
1353
|
"builder.fieldType.text": "Text",
|
|
1307
1354
|
"builder.fieldType.textarea": "Textarea",
|
|
@@ -1316,12 +1363,6 @@ var BUILDER_DEFAULTS = {
|
|
|
1316
1363
|
"builder.operator.contains": "contains",
|
|
1317
1364
|
"builder.operator.not_empty": "is not empty"
|
|
1318
1365
|
};
|
|
1319
|
-
function interpolate(template, params) {
|
|
1320
|
-
return template.replace(
|
|
1321
|
-
/\{\{(\w+)\}\}/g,
|
|
1322
|
-
(token, name) => Object.hasOwn(params, name) ? String(params[name]) : token
|
|
1323
|
-
);
|
|
1324
|
-
}
|
|
1325
1366
|
function BuilderSectionGroup({ children }) {
|
|
1326
1367
|
return children;
|
|
1327
1368
|
}
|
|
@@ -1526,20 +1567,14 @@ function FormBuilder({
|
|
|
1526
1567
|
const [isTranslating, setIsTranslating] = useState(false);
|
|
1527
1568
|
const [translationError, setTranslationError] = useState(null);
|
|
1528
1569
|
const [translationReport, setTranslationReport] = useState();
|
|
1529
|
-
const translate = (key, params = {}) =>
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
if (alias !== void 0) {
|
|
1538
|
-
const aliased = translator?.translate(alias, locale, translatorParams);
|
|
1539
|
-
if (aliased !== void 0 && aliased !== alias) return aliased;
|
|
1540
|
-
}
|
|
1541
|
-
return translated === void 0 ? interpolate(BUILDER_DEFAULTS[key] ?? key, params) : translated;
|
|
1542
|
-
};
|
|
1570
|
+
const translate = (key, params = {}) => resolveTranslation(
|
|
1571
|
+
key,
|
|
1572
|
+
BUILDER_TRANSLATION_ALIASES[key] === void 0 ? [] : [BUILDER_TRANSLATION_ALIASES[key]],
|
|
1573
|
+
translator,
|
|
1574
|
+
BUILDER_DEFAULTS,
|
|
1575
|
+
params,
|
|
1576
|
+
locale
|
|
1577
|
+
);
|
|
1543
1578
|
const pagesEnabled = features?.pages ?? true;
|
|
1544
1579
|
const localizationEnabled = features?.localization ?? true;
|
|
1545
1580
|
const conditionsEnabled = features?.conditions ?? true;
|
|
@@ -2828,7 +2863,7 @@ function FormProvider({
|
|
|
2828
2863
|
[initialValues, locale, onSubmit, resetOnSuccess, validSchema, values]
|
|
2829
2864
|
);
|
|
2830
2865
|
const translate = useCallback2(
|
|
2831
|
-
(key, params) => translator.translate(key, locale, params),
|
|
2866
|
+
(key, params) => translator.translate(key, locale, params) ?? key,
|
|
2832
2867
|
[locale, translator]
|
|
2833
2868
|
);
|
|
2834
2869
|
const contextValue = useMemo2(
|
|
@@ -3949,7 +3984,9 @@ export {
|
|
|
3949
3984
|
FormSubmissionError,
|
|
3950
3985
|
createLocalStorageSubmissionAttemptStore,
|
|
3951
3986
|
createLocalStorageSubmissionReceiptStore,
|
|
3987
|
+
isTranslationUnresolved,
|
|
3952
3988
|
resolveInitialFieldType,
|
|
3989
|
+
resolveTranslation,
|
|
3953
3990
|
submissionReceiptQueryKey,
|
|
3954
3991
|
useField,
|
|
3955
3992
|
useForm,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@form-engine-ts/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"typescript"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@form-engine-ts/core": "
|
|
46
|
-
"@form-engine-ts/privacy": "
|
|
45
|
+
"@form-engine-ts/core": "4.0.0",
|
|
46
|
+
"@form-engine-ts/privacy": "4.0.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"react": ">=18.2 <20",
|