@form-engine-ts/react 5.1.0 → 6.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/README.md +8 -0
- package/dist/index.cjs +319 -84
- package/dist/index.d.cts +99 -9
- package/dist/index.d.ts +99 -9
- package/dist/index.js +304 -64
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -27,7 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
FormEngineI18nProvider: () => FormEngineI18nProvider,
|
|
28
28
|
FormProvider: () => FormProvider,
|
|
29
29
|
FormRenderer: () => FormRenderer,
|
|
30
|
-
FormSubmissionError: () => FormSubmissionError,
|
|
30
|
+
FormSubmissionError: () => import_core8.FormSubmissionError,
|
|
31
31
|
createLocalStorageSubmissionAttemptStore: () => createLocalStorageSubmissionAttemptStore,
|
|
32
32
|
createLocalStorageSubmissionReceiptStore: () => createLocalStorageSubmissionReceiptStore,
|
|
33
33
|
isTranslationUnresolved: () => isTranslationUnresolved,
|
|
@@ -42,6 +42,7 @@ __export(index_exports, {
|
|
|
42
42
|
useFormBuilder: () => useFormBuilder,
|
|
43
43
|
useFormEngineI18n: () => useFormEngineI18n,
|
|
44
44
|
useSubmissionReceipts: () => useSubmissionReceipts,
|
|
45
|
+
useTranslationComparison: () => useTranslationComparison,
|
|
45
46
|
useTranslationWorkspace: () => useTranslationWorkspace,
|
|
46
47
|
validateLocalePipeline: () => validateLocalePipeline
|
|
47
48
|
});
|
|
@@ -978,6 +979,8 @@ function FormEngineI18nProvider({
|
|
|
978
979
|
fallbackLocale = "en",
|
|
979
980
|
messages,
|
|
980
981
|
customCatalogs,
|
|
982
|
+
onMissingKey,
|
|
983
|
+
strict,
|
|
981
984
|
translator: customTranslator,
|
|
982
985
|
children
|
|
983
986
|
}) {
|
|
@@ -987,9 +990,11 @@ function FormEngineI18nProvider({
|
|
|
987
990
|
locale,
|
|
988
991
|
fallbackLocale,
|
|
989
992
|
...messages === void 0 ? {} : { messages },
|
|
990
|
-
...customCatalogs === void 0 ? {} : { customCatalogs }
|
|
993
|
+
...customCatalogs === void 0 ? {} : { customCatalogs },
|
|
994
|
+
...onMissingKey === void 0 ? {} : { onMissingKey },
|
|
995
|
+
...strict === void 0 ? {} : { strict }
|
|
991
996
|
});
|
|
992
|
-
}, [customCatalogs, customTranslator, fallbackLocale, locale, messages]);
|
|
997
|
+
}, [customCatalogs, customTranslator, fallbackLocale, locale, messages, onMissingKey, strict]);
|
|
993
998
|
const value = (0, import_react2.useMemo)(() => ({ uiLocale: locale, translator }), [locale, translator]);
|
|
994
999
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormEngineI18nProviderScopeContext.Provider, { value: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormEngineI18nContext.Provider, { value, children }) });
|
|
995
1000
|
}
|
|
@@ -2566,6 +2571,7 @@ function FormBuilder({
|
|
|
2566
2571
|
LocalizationSlot,
|
|
2567
2572
|
{
|
|
2568
2573
|
schema,
|
|
2574
|
+
onChange,
|
|
2569
2575
|
translate,
|
|
2570
2576
|
currentLocale: editingLocale,
|
|
2571
2577
|
onCurrentLocaleChange: setEditingLocale,
|
|
@@ -3088,18 +3094,6 @@ function FormBuilder({
|
|
|
3088
3094
|
// src/context.tsx
|
|
3089
3095
|
var import_core4 = require("@form-engine-ts/core");
|
|
3090
3096
|
var import_react4 = require("react");
|
|
3091
|
-
|
|
3092
|
-
// src/types.ts
|
|
3093
|
-
var FormSubmissionError = class extends Error {
|
|
3094
|
-
payload;
|
|
3095
|
-
constructor(message, payload) {
|
|
3096
|
-
super(message);
|
|
3097
|
-
this.name = "FormSubmissionError";
|
|
3098
|
-
this.payload = payload ?? { formError: message };
|
|
3099
|
-
}
|
|
3100
|
-
};
|
|
3101
|
-
|
|
3102
|
-
// src/context.tsx
|
|
3103
3097
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
3104
3098
|
var FormContext = (0, import_react4.createContext)(null);
|
|
3105
3099
|
function issuesByField(issues) {
|
|
@@ -3236,10 +3230,12 @@ function FormProvider({
|
|
|
3236
3230
|
setSubmitStatus("success");
|
|
3237
3231
|
return response === void 0 ? { status: "success" } : { status: "success", response };
|
|
3238
3232
|
} catch (cause) {
|
|
3239
|
-
const error = isServerErrorPayload(cause) ? new FormSubmissionError(
|
|
3240
|
-
|
|
3241
|
-
cause
|
|
3242
|
-
|
|
3233
|
+
const error = (0, import_core4.isFormSubmissionSerializedError)(cause) ? new import_core4.FormSubmissionError(cause) : isServerErrorPayload(cause) ? new import_core4.FormSubmissionError({
|
|
3234
|
+
code: "VALIDATION_FAILED",
|
|
3235
|
+
messageKey: cause.formError ?? "Submission failed",
|
|
3236
|
+
fieldErrors: cause.fieldErrors ?? {},
|
|
3237
|
+
formErrors: cause.formError === void 0 ? [] : [cause.formError]
|
|
3238
|
+
}) : cause instanceof Error ? cause : new Error(String(cause));
|
|
3243
3239
|
setSubmitError(error);
|
|
3244
3240
|
setSubmitStatus("error");
|
|
3245
3241
|
return { status: "error", error };
|
|
@@ -3307,6 +3303,10 @@ function useField(fieldId) {
|
|
|
3307
3303
|
return { field, value: form.values[fieldId], error: form.errors[fieldId], setValue };
|
|
3308
3304
|
}
|
|
3309
3305
|
|
|
3306
|
+
// src/hooks/useTranslationComparison.ts
|
|
3307
|
+
var import_core6 = require("@form-engine-ts/core");
|
|
3308
|
+
var import_react6 = require("react");
|
|
3309
|
+
|
|
3310
3310
|
// src/hooks/useTranslationWorkspace.ts
|
|
3311
3311
|
var import_core5 = require("@form-engine-ts/core");
|
|
3312
3312
|
var import_react5 = require("react");
|
|
@@ -3421,26 +3421,27 @@ function workspaceLocaleValidationError(validation, currentLocales, requestedLoc
|
|
|
3421
3421
|
}
|
|
3422
3422
|
return { type: "custom_validation_failed", message: error.message };
|
|
3423
3423
|
}
|
|
3424
|
-
function
|
|
3424
|
+
function translationMetadata(sourceText, sourceLocale, mode) {
|
|
3425
3425
|
return {
|
|
3426
3426
|
sourceLocale,
|
|
3427
3427
|
sourceTextHash: (0, import_core5.computeSourceTextHash)(sourceText),
|
|
3428
|
-
translationSource:
|
|
3429
|
-
editedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3428
|
+
translationSource: mode,
|
|
3429
|
+
...mode === "manual" ? { editedAt: (/* @__PURE__ */ new Date()).toISOString() } : { translatedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
3430
3430
|
};
|
|
3431
3431
|
}
|
|
3432
|
-
function setNodeMetadata(node, slot, text, sourceLocale) {
|
|
3432
|
+
function setNodeMetadata(node, slot, text, sourceLocale, mode) {
|
|
3433
3433
|
const localeMetadata = node.translationMetadata?.[slot.locale];
|
|
3434
|
-
const nextMetadata = text.trim().length === 0 ? Object.fromEntries(Object.entries(localeMetadata ?? {}).filter(([key]) => key !== slot.property)) : { ...localeMetadata, [slot.property]:
|
|
3434
|
+
const nextMetadata = text.trim().length === 0 ? Object.fromEntries(Object.entries(localeMetadata ?? {}).filter(([key]) => key !== slot.property)) : { ...localeMetadata, [slot.property]: translationMetadata(slot.sourceText, sourceLocale, mode) };
|
|
3435
3435
|
return { ...node, translationMetadata: { ...node.translationMetadata, [slot.locale]: nextMetadata } };
|
|
3436
3436
|
}
|
|
3437
|
-
function updateSchemaTranslation(schema, slot, text, sourceLocale) {
|
|
3437
|
+
function updateSchemaTranslation(schema, slot, text, sourceLocale, mode = "manual") {
|
|
3438
3438
|
if (slot.kind === "form") {
|
|
3439
3439
|
return setNodeMetadata(
|
|
3440
3440
|
{ ...schema, translations: updateTranslationMap(schema.translations, slot.locale, slot.property, text) },
|
|
3441
3441
|
slot,
|
|
3442
3442
|
text,
|
|
3443
|
-
sourceLocale
|
|
3443
|
+
sourceLocale,
|
|
3444
|
+
mode
|
|
3444
3445
|
);
|
|
3445
3446
|
}
|
|
3446
3447
|
if (slot.kind === "field") {
|
|
@@ -3449,7 +3450,7 @@ function updateSchemaTranslation(schema, slot, text, sourceLocale) {
|
|
|
3449
3450
|
fields: schema.fields.map((field) => {
|
|
3450
3451
|
if (field.id !== slot.nodeId) return field;
|
|
3451
3452
|
const translations = updateTranslationMap(field.translations, slot.locale, slot.property, text);
|
|
3452
|
-
return setNodeMetadata({ ...field, translations }, slot, text, sourceLocale);
|
|
3453
|
+
return setNodeMetadata({ ...field, translations }, slot, text, sourceLocale, mode);
|
|
3453
3454
|
})
|
|
3454
3455
|
};
|
|
3455
3456
|
}
|
|
@@ -3465,7 +3466,7 @@ function updateSchemaTranslation(schema, slot, text, sourceLocale) {
|
|
|
3465
3466
|
const translations = text.trim().length === 0 ? Object.fromEntries(
|
|
3466
3467
|
Object.entries(option.translations ?? {}).filter(([locale]) => locale !== slot.locale)
|
|
3467
3468
|
) : { ...option.translations, [slot.locale]: text };
|
|
3468
|
-
return setNodeMetadata({ ...option, translations }, slot, text, sourceLocale);
|
|
3469
|
+
return setNodeMetadata({ ...option, translations }, slot, text, sourceLocale, mode);
|
|
3469
3470
|
})
|
|
3470
3471
|
};
|
|
3471
3472
|
})
|
|
@@ -3477,7 +3478,7 @@ function updateSchemaTranslation(schema, slot, text, sourceLocale) {
|
|
|
3477
3478
|
pages: schema.pages.map((page) => {
|
|
3478
3479
|
if (page.id !== slot.nodeId) return page;
|
|
3479
3480
|
const translations = updateTranslationMap(page.translations, slot.locale, slot.property, text);
|
|
3480
|
-
return setNodeMetadata({ ...page, translations }, slot, text, sourceLocale);
|
|
3481
|
+
return setNodeMetadata({ ...page, translations }, slot, text, sourceLocale, mode);
|
|
3481
3482
|
})
|
|
3482
3483
|
}
|
|
3483
3484
|
};
|
|
@@ -3495,13 +3496,22 @@ function useTranslationWorkspace({
|
|
|
3495
3496
|
onLocaleRemoved,
|
|
3496
3497
|
onLocaleChange,
|
|
3497
3498
|
beforeRemoveLocale,
|
|
3499
|
+
confirmRemoveLocale,
|
|
3500
|
+
slots: workspaceSlots,
|
|
3501
|
+
onTranslationStart,
|
|
3502
|
+
onTranslationSuccess,
|
|
3503
|
+
onTranslationError,
|
|
3504
|
+
onTranslationChange,
|
|
3498
3505
|
validateLocale
|
|
3499
3506
|
}) {
|
|
3500
3507
|
const [draftSchema, setDraftSchema] = (0, import_react5.useState)(schema);
|
|
3501
3508
|
const [selectedLocale, setSelectedLocale] = (0, import_react5.useState)((0, import_core5.normalizeLocale)(targetLocale ?? "") ?? targetLocale ?? "");
|
|
3502
3509
|
const [isTranslating, setIsTranslating] = (0, import_react5.useState)(false);
|
|
3503
3510
|
const [error, setError] = (0, import_react5.useState)();
|
|
3511
|
+
const [pendingRemoval, setPendingRemoval] = (0, import_react5.useState)();
|
|
3512
|
+
const pendingRemovalResolver = (0, import_react5.useRef)(void 0);
|
|
3504
3513
|
const currentSchema = onChange === void 0 ? draftSchema : schema;
|
|
3514
|
+
const confirmRemoveLocaleRenderer = confirmRemoveLocale ?? workspaceSlots?.confirmRemoveLocale;
|
|
3505
3515
|
const targetLocales = (0, import_react5.useMemo)(() => {
|
|
3506
3516
|
const locales = (0, import_core5.collectSchemaLocales)(currentSchema).allUniqueLocales;
|
|
3507
3517
|
return [.../* @__PURE__ */ new Set([...currentSchema.supportedLocales ?? [], ...locales])].filter(
|
|
@@ -3551,9 +3561,17 @@ function useTranslationWorkspace({
|
|
|
3551
3561
|
const setTranslation = (0, import_react5.useCallback)(
|
|
3552
3562
|
(slot, text) => {
|
|
3553
3563
|
if (readOnly) return;
|
|
3554
|
-
|
|
3564
|
+
const metadata = translationMetadata(slot.sourceText, sourceLocale, "manual");
|
|
3565
|
+
commit(updateSchemaTranslation(currentSchema, slot, text, sourceLocale, "manual"));
|
|
3566
|
+
onTranslationChange?.({
|
|
3567
|
+
slot,
|
|
3568
|
+
...slot.existingText === void 0 ? {} : { previousText: slot.existingText },
|
|
3569
|
+
nextText: text,
|
|
3570
|
+
mode: "manual",
|
|
3571
|
+
metadata
|
|
3572
|
+
});
|
|
3555
3573
|
},
|
|
3556
|
-
[commit, currentSchema, readOnly, sourceLocale]
|
|
3574
|
+
[commit, currentSchema, onTranslationChange, readOnly, sourceLocale]
|
|
3557
3575
|
);
|
|
3558
3576
|
const addLocale = (0, import_react5.useCallback)(
|
|
3559
3577
|
(locale) => {
|
|
@@ -3614,21 +3632,36 @@ function useTranslationWorkspace({
|
|
|
3614
3632
|
onLocaleRemoved?.(normalized);
|
|
3615
3633
|
};
|
|
3616
3634
|
const slotCount = (0, import_core5.collectTranslationSlots)(currentSchema, normalized).length;
|
|
3635
|
+
const translatedSlotsCount = (0, import_core5.collectTranslationSlots)(currentSchema, normalized).filter(
|
|
3636
|
+
(slot) => slot.existingText !== void 0 && slot.existingText.trim().length > 0
|
|
3637
|
+
).length;
|
|
3638
|
+
const requestConfirmation = () => new Promise((resolve) => {
|
|
3639
|
+
pendingRemovalResolver.current = resolve;
|
|
3640
|
+
setPendingRemoval({
|
|
3641
|
+
locale: normalized,
|
|
3642
|
+
localeLabel: localeOptions.find((option) => option.locale === normalized)?.label ?? normalized,
|
|
3643
|
+
translatedSlotsCount
|
|
3644
|
+
});
|
|
3645
|
+
});
|
|
3646
|
+
const removeAfterApproval = () => {
|
|
3647
|
+
if (confirmRemoveLocaleRenderer === void 0) {
|
|
3648
|
+
remove();
|
|
3649
|
+
return true;
|
|
3650
|
+
}
|
|
3651
|
+
return requestConfirmation();
|
|
3652
|
+
};
|
|
3617
3653
|
if (beforeRemoveLocale === void 0) {
|
|
3618
|
-
|
|
3619
|
-
return true;
|
|
3654
|
+
return removeAfterApproval();
|
|
3620
3655
|
}
|
|
3621
3656
|
try {
|
|
3622
3657
|
const decision = beforeRemoveLocale(normalized, { slotCount });
|
|
3623
3658
|
if (typeof decision === "boolean") {
|
|
3624
3659
|
if (!decision) return false;
|
|
3625
|
-
|
|
3626
|
-
return true;
|
|
3660
|
+
return removeAfterApproval();
|
|
3627
3661
|
}
|
|
3628
3662
|
return decision.then((allowed) => {
|
|
3629
3663
|
if (!allowed) return false;
|
|
3630
|
-
|
|
3631
|
-
return true;
|
|
3664
|
+
return removeAfterApproval();
|
|
3632
3665
|
});
|
|
3633
3666
|
} catch (cause) {
|
|
3634
3667
|
const workspaceError = {
|
|
@@ -3640,8 +3673,45 @@ function useTranslationWorkspace({
|
|
|
3640
3673
|
return Promise.reject(cause);
|
|
3641
3674
|
}
|
|
3642
3675
|
},
|
|
3643
|
-
[
|
|
3676
|
+
[
|
|
3677
|
+
activeLocale,
|
|
3678
|
+
beforeRemoveLocale,
|
|
3679
|
+
commit,
|
|
3680
|
+
confirmRemoveLocaleRenderer,
|
|
3681
|
+
currentSchema,
|
|
3682
|
+
localeOptions,
|
|
3683
|
+
onLocaleRemoved,
|
|
3684
|
+
readOnly,
|
|
3685
|
+
sourceLocale
|
|
3686
|
+
]
|
|
3644
3687
|
);
|
|
3688
|
+
const confirmPendingRemoval = (0, import_react5.useCallback)(() => {
|
|
3689
|
+
const pending = pendingRemoval;
|
|
3690
|
+
const resolve = pendingRemovalResolver.current;
|
|
3691
|
+
if (pending === void 0 || resolve === void 0) return;
|
|
3692
|
+
pendingRemovalResolver.current = void 0;
|
|
3693
|
+
setPendingRemoval(void 0);
|
|
3694
|
+
commit((0, import_core5.removeLocaleFromSchema)(currentSchema, pending.locale));
|
|
3695
|
+
if (activeLocale === pending.locale) setSelectedLocale("");
|
|
3696
|
+
onLocaleRemoved?.(pending.locale);
|
|
3697
|
+
resolve(true);
|
|
3698
|
+
}, [activeLocale, commit, currentSchema, onLocaleRemoved, pendingRemoval]);
|
|
3699
|
+
const cancelPendingRemoval = (0, import_react5.useCallback)(() => {
|
|
3700
|
+
const resolve = pendingRemovalResolver.current;
|
|
3701
|
+
if (resolve === void 0) return;
|
|
3702
|
+
pendingRemovalResolver.current = void 0;
|
|
3703
|
+
setPendingRemoval(void 0);
|
|
3704
|
+
resolve(false);
|
|
3705
|
+
}, []);
|
|
3706
|
+
const removeLocaleConfirmation = (0, import_react5.useMemo)(() => {
|
|
3707
|
+
if (confirmRemoveLocaleRenderer === void 0 || pendingRemoval === void 0) return null;
|
|
3708
|
+
return confirmRemoveLocaleRenderer({
|
|
3709
|
+
...pendingRemoval,
|
|
3710
|
+
isOpen: true,
|
|
3711
|
+
onConfirm: confirmPendingRemoval,
|
|
3712
|
+
onCancel: cancelPendingRemoval
|
|
3713
|
+
});
|
|
3714
|
+
}, [cancelPendingRemoval, confirmPendingRemoval, confirmRemoveLocaleRenderer, pendingRemoval]);
|
|
3645
3715
|
const translateAll = (0, import_react5.useCallback)(
|
|
3646
3716
|
async (options = {}) => {
|
|
3647
3717
|
if (readOnly) {
|
|
@@ -3678,6 +3748,7 @@ function useTranslationWorkspace({
|
|
|
3678
3748
|
}
|
|
3679
3749
|
setIsTranslating(true);
|
|
3680
3750
|
setError(void 0);
|
|
3751
|
+
onTranslationStart?.({ targetLocale: activeLocale, mode: "automatic" });
|
|
3681
3752
|
try {
|
|
3682
3753
|
const populated = await (0, import_core5.populateSchemaTranslations)(
|
|
3683
3754
|
currentSchema,
|
|
@@ -3690,6 +3761,17 @@ function useTranslationWorkspace({
|
|
|
3690
3761
|
}
|
|
3691
3762
|
);
|
|
3692
3763
|
commit(populated.schema);
|
|
3764
|
+
const missingSlotsCount = (0, import_core5.collectTranslationSlots)(populated.schema, activeLocale).filter(
|
|
3765
|
+
(slot) => slot.status === "missing"
|
|
3766
|
+
).length;
|
|
3767
|
+
onTranslationSuccess?.({
|
|
3768
|
+
sourceLocale,
|
|
3769
|
+
targetLocale: activeLocale,
|
|
3770
|
+
mode: "automatic",
|
|
3771
|
+
updatedSlots: populated.report.updatedSlots,
|
|
3772
|
+
skippedSlots: populated.report.skippedSlots,
|
|
3773
|
+
missingSlotsCount
|
|
3774
|
+
});
|
|
3693
3775
|
return { success: true, report: populated.report };
|
|
3694
3776
|
} catch (cause) {
|
|
3695
3777
|
const workspaceError = {
|
|
@@ -3698,12 +3780,25 @@ function useTranslationWorkspace({
|
|
|
3698
3780
|
cause
|
|
3699
3781
|
};
|
|
3700
3782
|
setError(workspaceError);
|
|
3783
|
+
onTranslationError?.({ targetLocale: activeLocale, error: workspaceError });
|
|
3701
3784
|
return { success: false, error: workspaceError };
|
|
3702
3785
|
} finally {
|
|
3703
3786
|
setIsTranslating(false);
|
|
3704
3787
|
}
|
|
3705
3788
|
},
|
|
3706
|
-
[
|
|
3789
|
+
[
|
|
3790
|
+
activeLocale,
|
|
3791
|
+
commit,
|
|
3792
|
+
currentSchema,
|
|
3793
|
+
localeOptions,
|
|
3794
|
+
onTranslationError,
|
|
3795
|
+
onTranslationStart,
|
|
3796
|
+
onTranslationSuccess,
|
|
3797
|
+
readOnly,
|
|
3798
|
+
slots,
|
|
3799
|
+
sourceLocale,
|
|
3800
|
+
translationAdapter
|
|
3801
|
+
]
|
|
3707
3802
|
);
|
|
3708
3803
|
const translateSlot = (0, import_react5.useCallback)(
|
|
3709
3804
|
async (slot) => {
|
|
@@ -3721,7 +3816,15 @@ function useTranslationWorkspace({
|
|
|
3721
3816
|
setError(void 0);
|
|
3722
3817
|
try {
|
|
3723
3818
|
const text = await asAsyncAdapter(translationAdapter).translateText(slot.sourceText, slot.locale, sourceLocale);
|
|
3724
|
-
|
|
3819
|
+
const metadata = translationMetadata(slot.sourceText, sourceLocale, "automatic");
|
|
3820
|
+
commit(updateSchemaTranslation(currentSchema, slot, text, sourceLocale, "automatic"));
|
|
3821
|
+
onTranslationChange?.({
|
|
3822
|
+
slot,
|
|
3823
|
+
...slot.existingText === void 0 ? {} : { previousText: slot.existingText },
|
|
3824
|
+
nextText: text,
|
|
3825
|
+
mode: "automatic",
|
|
3826
|
+
metadata
|
|
3827
|
+
});
|
|
3725
3828
|
return { success: true };
|
|
3726
3829
|
} catch (cause) {
|
|
3727
3830
|
const workspaceError = {
|
|
@@ -3735,7 +3838,7 @@ function useTranslationWorkspace({
|
|
|
3735
3838
|
setIsTranslating(false);
|
|
3736
3839
|
}
|
|
3737
3840
|
},
|
|
3738
|
-
[commit, currentSchema, readOnly, sourceLocale, translationAdapter]
|
|
3841
|
+
[commit, currentSchema, onTranslationChange, readOnly, sourceLocale, translationAdapter]
|
|
3739
3842
|
);
|
|
3740
3843
|
return {
|
|
3741
3844
|
sourceLocale,
|
|
@@ -3752,6 +3855,7 @@ function useTranslationWorkspace({
|
|
|
3752
3855
|
addLocale,
|
|
3753
3856
|
isAddLocaleAllowed,
|
|
3754
3857
|
removeLocale,
|
|
3858
|
+
...removeLocaleConfirmation === null ? {} : { removeLocaleConfirmation },
|
|
3755
3859
|
setTranslation,
|
|
3756
3860
|
translateAll,
|
|
3757
3861
|
translateSlot,
|
|
@@ -3760,8 +3864,131 @@ function useTranslationWorkspace({
|
|
|
3760
3864
|
};
|
|
3761
3865
|
}
|
|
3762
3866
|
|
|
3867
|
+
// src/hooks/useTranslationComparison.ts
|
|
3868
|
+
function canonicalMetadata(metadata, sourceText, sourceLocale, translatedText) {
|
|
3869
|
+
if (translatedText === void 0 || translatedText.trim().length === 0) return void 0;
|
|
3870
|
+
if (metadata !== void 0 && typeof metadata.sourceLocale === "string" && typeof metadata.sourceTextHash === "string" && (metadata.translationSource === "automatic" || metadata.translationSource === "manual")) {
|
|
3871
|
+
return {
|
|
3872
|
+
sourceLocale: metadata.sourceLocale,
|
|
3873
|
+
sourceTextHash: metadata.sourceTextHash,
|
|
3874
|
+
translationSource: metadata.translationSource,
|
|
3875
|
+
...typeof metadata.translatedAt === "string" ? { translatedAt: metadata.translatedAt } : {},
|
|
3876
|
+
...typeof metadata.editedAt === "string" ? { editedAt: metadata.editedAt } : {}
|
|
3877
|
+
};
|
|
3878
|
+
}
|
|
3879
|
+
return {
|
|
3880
|
+
sourceLocale: typeof metadata?.sourceLocale === "string" ? metadata.sourceLocale : sourceLocale,
|
|
3881
|
+
sourceTextHash: (0, import_core6.computeSourceTextHash)(sourceText),
|
|
3882
|
+
translationSource: metadata?.isManual === true || metadata?.isManuallyEdited === true || metadata?.translationSource === "manual" ? "manual" : "automatic"
|
|
3883
|
+
};
|
|
3884
|
+
}
|
|
3885
|
+
function optionParentId(slot) {
|
|
3886
|
+
if (slot.kind !== "option" || slot.path === void 0) return void 0;
|
|
3887
|
+
return /^fields\.([^.]+)\.options\./u.exec(slot.path)?.[1];
|
|
3888
|
+
}
|
|
3889
|
+
function getNodeTitle(schema, slot) {
|
|
3890
|
+
if (slot.kind === "field") return schema.fields.find((field) => field.id === slot.nodeId)?.title;
|
|
3891
|
+
if (slot.kind === "page") return schema.pages?.find((page) => page.id === slot.nodeId)?.title;
|
|
3892
|
+
if (slot.kind === "option") return schema.fields.find((field) => field.id === optionParentId(slot))?.title;
|
|
3893
|
+
return void 0;
|
|
3894
|
+
}
|
|
3895
|
+
function comparisonItem(schema, slot, sourceLocale, hasAdapter) {
|
|
3896
|
+
const path = slot.path ?? `${slot.kind}.${slot.nodeId}.${slot.property}`;
|
|
3897
|
+
const nodeTitle = getNodeTitle(schema, slot);
|
|
3898
|
+
const metadata = canonicalMetadata(
|
|
3899
|
+
slot.existingTranslationMetadata,
|
|
3900
|
+
slot.sourceText,
|
|
3901
|
+
sourceLocale,
|
|
3902
|
+
slot.existingText
|
|
3903
|
+
);
|
|
3904
|
+
return {
|
|
3905
|
+
id: path,
|
|
3906
|
+
path,
|
|
3907
|
+
targetKind: slot.kind,
|
|
3908
|
+
targetProperty: slot.property,
|
|
3909
|
+
...nodeTitle === void 0 ? {} : { nodeTitle },
|
|
3910
|
+
sourceText: slot.sourceText,
|
|
3911
|
+
translatedText: slot.existingText ?? "",
|
|
3912
|
+
status: slot.status ?? "missing",
|
|
3913
|
+
...metadata === void 0 ? {} : { metadata },
|
|
3914
|
+
translatable: hasAdapter && slot.sourceText.trim().length > 0
|
|
3915
|
+
};
|
|
3916
|
+
}
|
|
3917
|
+
function summaryFor(items) {
|
|
3918
|
+
const counts = {
|
|
3919
|
+
missing: 0,
|
|
3920
|
+
translated: 0,
|
|
3921
|
+
stale: 0,
|
|
3922
|
+
manual: 0,
|
|
3923
|
+
"manual-stale": 0
|
|
3924
|
+
};
|
|
3925
|
+
for (const item of items) counts[item.status] += 1;
|
|
3926
|
+
return {
|
|
3927
|
+
total: items.length,
|
|
3928
|
+
translated: counts.translated + counts.manual,
|
|
3929
|
+
missing: counts.missing,
|
|
3930
|
+
stale: counts.stale + counts["manual-stale"],
|
|
3931
|
+
manual: counts.manual + counts["manual-stale"]
|
|
3932
|
+
};
|
|
3933
|
+
}
|
|
3934
|
+
function useTranslationComparison({
|
|
3935
|
+
schema,
|
|
3936
|
+
sourceLocale = schema.defaultLocale ?? "en",
|
|
3937
|
+
targetLocale,
|
|
3938
|
+
translationAdapter,
|
|
3939
|
+
readOnly = false,
|
|
3940
|
+
onChange,
|
|
3941
|
+
onTranslationChange
|
|
3942
|
+
}) {
|
|
3943
|
+
const workspace = useTranslationWorkspace({
|
|
3944
|
+
schema,
|
|
3945
|
+
sourceLocale,
|
|
3946
|
+
targetLocale,
|
|
3947
|
+
...translationAdapter === void 0 ? {} : { translationAdapter },
|
|
3948
|
+
readOnly,
|
|
3949
|
+
...onChange === void 0 ? {} : { onChange },
|
|
3950
|
+
...onTranslationChange === void 0 ? {} : { onTranslationChange }
|
|
3951
|
+
});
|
|
3952
|
+
const items = (0, import_react6.useMemo)(
|
|
3953
|
+
() => workspace.slots.map((slot) => comparisonItem(schema, slot, sourceLocale, translationAdapter !== void 0)),
|
|
3954
|
+
[schema, sourceLocale, translationAdapter, workspace.slots]
|
|
3955
|
+
);
|
|
3956
|
+
const itemByPath = (0, import_react6.useMemo)(() => new Map(workspace.slots.map((slot) => [slot.path, slot])), [workspace.slots]);
|
|
3957
|
+
const updateTranslation = (0, import_react6.useCallback)(
|
|
3958
|
+
(path, text) => {
|
|
3959
|
+
const slot = itemByPath.get(path);
|
|
3960
|
+
if (slot !== void 0) workspace.setTranslation(slot, text);
|
|
3961
|
+
},
|
|
3962
|
+
[itemByPath, workspace]
|
|
3963
|
+
);
|
|
3964
|
+
const translateSingle = (0, import_react6.useCallback)(
|
|
3965
|
+
async (path) => {
|
|
3966
|
+
const slot = itemByPath.get(path);
|
|
3967
|
+
if (slot === void 0) return;
|
|
3968
|
+
const result = await workspace.translateSlot(slot);
|
|
3969
|
+
if (!result.success) throw new Error(result.error?.type ?? "Translation failed.");
|
|
3970
|
+
},
|
|
3971
|
+
[itemByPath, workspace]
|
|
3972
|
+
);
|
|
3973
|
+
const translateAll = (0, import_react6.useCallback)(async () => {
|
|
3974
|
+
const result = await workspace.translateAll();
|
|
3975
|
+
if (result.report !== void 0) return result.report;
|
|
3976
|
+
throw new Error(result.error?.type ?? "Translation failed.");
|
|
3977
|
+
}, [workspace]);
|
|
3978
|
+
return {
|
|
3979
|
+
sourceLocale: workspace.sourceLocale,
|
|
3980
|
+
targetLocale: workspace.targetLocale,
|
|
3981
|
+
items,
|
|
3982
|
+
summary: summaryFor(items),
|
|
3983
|
+
isTranslating: workspace.isTranslating,
|
|
3984
|
+
updateTranslation,
|
|
3985
|
+
translateSingle,
|
|
3986
|
+
translateAll
|
|
3987
|
+
};
|
|
3988
|
+
}
|
|
3989
|
+
|
|
3763
3990
|
// src/receipt.ts
|
|
3764
|
-
var
|
|
3991
|
+
var import_react7 = require("react");
|
|
3765
3992
|
function submissionReceiptQueryKey(formId, formVersion) {
|
|
3766
3993
|
return `${formId}:v${formVersion}`;
|
|
3767
3994
|
}
|
|
@@ -3832,19 +4059,19 @@ function createLocalStorageSubmissionReceiptStore(options = {}) {
|
|
|
3832
4059
|
}
|
|
3833
4060
|
function useSubmissionReceipts(store, queries) {
|
|
3834
4061
|
const querySignature = JSON.stringify(queries.map(({ formId, formVersion }) => [formId, formVersion]));
|
|
3835
|
-
const stableQueries = (0,
|
|
4062
|
+
const stableQueries = (0, import_react7.useMemo)(() => {
|
|
3836
4063
|
const parsed = JSON.parse(querySignature);
|
|
3837
4064
|
if (!Array.isArray(parsed)) return [];
|
|
3838
4065
|
return parsed.flatMap(
|
|
3839
4066
|
(entry) => Array.isArray(entry) && typeof entry[0] === "string" && typeof entry[1] === "number" && Number.isSafeInteger(entry[1]) ? [{ formId: entry[0], formVersion: entry[1] }] : []
|
|
3840
4067
|
);
|
|
3841
4068
|
}, [querySignature]);
|
|
3842
|
-
const [state, setState] = (0,
|
|
4069
|
+
const [state, setState] = (0, import_react7.useState)({
|
|
3843
4070
|
receipts: /* @__PURE__ */ new Map(),
|
|
3844
4071
|
isLoading: stableQueries.length > 0,
|
|
3845
4072
|
error: null
|
|
3846
4073
|
});
|
|
3847
|
-
(0,
|
|
4074
|
+
(0, import_react7.useEffect)(() => {
|
|
3848
4075
|
let active = true;
|
|
3849
4076
|
if (stableQueries.length === 0) {
|
|
3850
4077
|
setState({ receipts: /* @__PURE__ */ new Map(), isLoading: false, error: null });
|
|
@@ -3878,8 +4105,8 @@ function useSubmissionReceipts(store, queries) {
|
|
|
3878
4105
|
}
|
|
3879
4106
|
|
|
3880
4107
|
// src/renderer.tsx
|
|
3881
|
-
var
|
|
3882
|
-
var
|
|
4108
|
+
var import_core7 = require("@form-engine-ts/core");
|
|
4109
|
+
var import_react8 = require("react");
|
|
3883
4110
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
3884
4111
|
var isChoiceFieldType = (type) => type === "radio" || type === "checkbox" || type === "multi-select" || type === "select";
|
|
3885
4112
|
function resolveChoiceFieldLayout(type, appearance, groupedChoiceFieldsLegacy = false) {
|
|
@@ -4391,33 +4618,33 @@ function ContextFormRenderer({
|
|
|
4391
4618
|
}) {
|
|
4392
4619
|
const form = useForm();
|
|
4393
4620
|
const i18n = useFormEngineI18n();
|
|
4394
|
-
const isProviderValue = (0,
|
|
4395
|
-
const prefix = (0,
|
|
4396
|
-
const formRef = (0,
|
|
4397
|
-
const loadedDraftKey = (0,
|
|
4398
|
-
const [draftRestored, setDraftRestored] = (0,
|
|
4399
|
-
const [currentPageIndex, setCurrentPageIndex] = (0,
|
|
4400
|
-
const [focusFieldId, setFocusFieldId] = (0,
|
|
4401
|
-
const [confirmation, setConfirmation] = (0,
|
|
4402
|
-
const [guardMessage, setGuardMessage] = (0,
|
|
4403
|
-
const [guardsPending, setGuardsPending] = (0,
|
|
4404
|
-
const [receipt, setReceipt] = (0,
|
|
4405
|
-
const [completionData, setCompletionData] = (0,
|
|
4406
|
-
const [receiptLoaded, setReceiptLoaded] = (0,
|
|
4407
|
-
const rendererSubmissionInFlight = (0,
|
|
4408
|
-
const fallbackAttemptId = (0,
|
|
4409
|
-
const completionRef = (0,
|
|
4410
|
-
const confirmationRef = (0,
|
|
4621
|
+
const isProviderValue = (0, import_react8.useContext)(FormEngineI18nProviderScopeContext);
|
|
4622
|
+
const prefix = (0, import_react8.useId)().replace(/:/g, "");
|
|
4623
|
+
const formRef = (0, import_react8.useRef)(null);
|
|
4624
|
+
const loadedDraftKey = (0, import_react8.useRef)(null);
|
|
4625
|
+
const [draftRestored, setDraftRestored] = (0, import_react8.useState)(false);
|
|
4626
|
+
const [currentPageIndex, setCurrentPageIndex] = (0, import_react8.useState)(0);
|
|
4627
|
+
const [focusFieldId, setFocusFieldId] = (0, import_react8.useState)(null);
|
|
4628
|
+
const [confirmation, setConfirmation] = (0, import_react8.useState)(null);
|
|
4629
|
+
const [guardMessage, setGuardMessage] = (0, import_react8.useState)(null);
|
|
4630
|
+
const [guardsPending, setGuardsPending] = (0, import_react8.useState)(false);
|
|
4631
|
+
const [receipt, setReceipt] = (0, import_react8.useState)(null);
|
|
4632
|
+
const [completionData, setCompletionData] = (0, import_react8.useState)(null);
|
|
4633
|
+
const [receiptLoaded, setReceiptLoaded] = (0, import_react8.useState)(receiptStore === void 0);
|
|
4634
|
+
const rendererSubmissionInFlight = (0, import_react8.useRef)(false);
|
|
4635
|
+
const fallbackAttemptId = (0, import_react8.useRef)(null);
|
|
4636
|
+
const completionRef = (0, import_react8.useRef)(null);
|
|
4637
|
+
const confirmationRef = (0, import_react8.useRef)(null);
|
|
4411
4638
|
const pages = form.schema.pages;
|
|
4412
|
-
const visiblePageIndexes = (0,
|
|
4639
|
+
const visiblePageIndexes = (0, import_react8.useMemo)(
|
|
4413
4640
|
() => pages === void 0 ? [] : pages.flatMap((page, index) => form.pageVisibility[page.id] === true ? [index] : []),
|
|
4414
4641
|
[form.pageVisibility, pages]
|
|
4415
4642
|
);
|
|
4416
4643
|
const activePage = pages?.[currentPageIndex];
|
|
4417
4644
|
const activeVisibleIndex = visiblePageIndexes.indexOf(currentPageIndex);
|
|
4418
4645
|
const fieldIds = activePage === void 0 ? void 0 : new Set(activePage.questionIds);
|
|
4419
|
-
const visibleValues = (0,
|
|
4420
|
-
const visibleItems = (0,
|
|
4646
|
+
const visibleValues = (0, import_react8.useMemo)(() => (0, import_core7.selectVisibleAnswers)(form.schema, form.values), [form.schema, form.values]);
|
|
4647
|
+
const visibleItems = (0, import_react8.useMemo)(
|
|
4421
4648
|
() => buildSubmittedItems(form.schema, form.values, form.visibility, (key) => form.translate(key), false),
|
|
4422
4649
|
[form.schema, form.translate, form.values, form.visibility]
|
|
4423
4650
|
);
|
|
@@ -4426,7 +4653,7 @@ function ContextFormRenderer({
|
|
|
4426
4653
|
const submitState = confirmation === null && !guardsPending ? form.submitStatus : "confirming";
|
|
4427
4654
|
const interactionLocked = submitState === "confirming" || submitState === "submitting";
|
|
4428
4655
|
const isReplaceMode = successRenderMode === "replace" || hideFormOnSuccess;
|
|
4429
|
-
const resolveMessage = (0,
|
|
4656
|
+
const resolveMessage = (0, import_react8.useCallback)(
|
|
4430
4657
|
(key, fallback) => {
|
|
4431
4658
|
const providerDefault = isProviderValue ? i18n.translator(`renderer.${key}`) : void 0;
|
|
4432
4659
|
const defaultText = fallback ?? (providerDefault === "" ? void 0 : providerDefault) ?? DEFAULT_RENDERER_MESSAGES[form.locale.toLowerCase().startsWith("ja") ? "ja" : "en"][key] ?? key;
|
|
@@ -4435,15 +4662,15 @@ function ContextFormRenderer({
|
|
|
4435
4662
|
},
|
|
4436
4663
|
[form.locale, i18n, isProviderValue, messageResolver, messages]
|
|
4437
4664
|
);
|
|
4438
|
-
const fieldTranslate = (0,
|
|
4665
|
+
const fieldTranslate = (0, import_react8.useCallback)(
|
|
4439
4666
|
(key, params) => key === "validation.required" && (messages.requiredField !== void 0 || messageResolver !== void 0) ? resolveMessage("requiredField") : form.translate(key, params),
|
|
4440
4667
|
[form.translate, messageResolver, messages.requiredField, resolveMessage]
|
|
4441
4668
|
);
|
|
4442
|
-
const focusSubmitButton = (0,
|
|
4669
|
+
const focusSubmitButton = (0, import_react8.useCallback)(() => {
|
|
4443
4670
|
const button = formRef.current?.querySelector(".fe-submit, button[type='submit'], button");
|
|
4444
4671
|
button?.focus();
|
|
4445
4672
|
}, []);
|
|
4446
|
-
(0,
|
|
4673
|
+
(0, import_react8.useEffect)(() => {
|
|
4447
4674
|
let active = true;
|
|
4448
4675
|
if (receiptStore === void 0) {
|
|
4449
4676
|
setReceipt(null);
|
|
@@ -4464,14 +4691,14 @@ function ContextFormRenderer({
|
|
|
4464
4691
|
active = false;
|
|
4465
4692
|
};
|
|
4466
4693
|
}, [form.schema.id, form.schema.version, receiptStore]);
|
|
4467
|
-
(0,
|
|
4694
|
+
(0, import_react8.useEffect)(() => {
|
|
4468
4695
|
if (pages === void 0 || visiblePageIndexes.length === 0) {
|
|
4469
4696
|
setCurrentPageIndex(0);
|
|
4470
4697
|
return;
|
|
4471
4698
|
}
|
|
4472
4699
|
if (!visiblePageIndexes.includes(currentPageIndex)) setCurrentPageIndex(visiblePageIndexes[0] ?? 0);
|
|
4473
4700
|
}, [currentPageIndex, pages, visiblePageIndexes]);
|
|
4474
|
-
(0,
|
|
4701
|
+
(0, import_react8.useEffect)(() => {
|
|
4475
4702
|
if (focusFieldId === null) return;
|
|
4476
4703
|
const fieldContainer = [...formRef.current?.querySelectorAll("[data-field-id]") ?? []].find(
|
|
4477
4704
|
(element) => element.dataset.fieldId === focusFieldId
|
|
@@ -4483,11 +4710,11 @@ function ContextFormRenderer({
|
|
|
4483
4710
|
setFocusFieldId(null);
|
|
4484
4711
|
}
|
|
4485
4712
|
}, [focusFieldId]);
|
|
4486
|
-
(0,
|
|
4713
|
+
(0, import_react8.useEffect)(() => {
|
|
4487
4714
|
if (!isReplaceMode || form.submitStatus !== "success") return;
|
|
4488
4715
|
completionRef.current?.focus();
|
|
4489
4716
|
}, [form.submitStatus, isReplaceMode]);
|
|
4490
|
-
(0,
|
|
4717
|
+
(0, import_react8.useEffect)(() => {
|
|
4491
4718
|
if (confirmation === null) return;
|
|
4492
4719
|
const confirmButton = confirmationRef.current?.querySelector("[data-fe-confirm], button");
|
|
4493
4720
|
confirmButton?.focus();
|
|
@@ -4519,7 +4746,7 @@ function ContextFormRenderer({
|
|
|
4519
4746
|
globalThis.addEventListener("keydown", onKeyDown);
|
|
4520
4747
|
return () => globalThis.removeEventListener("keydown", onKeyDown);
|
|
4521
4748
|
}, [confirmation, confirmationRenderMode, focusSubmitButton]);
|
|
4522
|
-
(0,
|
|
4749
|
+
(0, import_react8.useEffect)(() => {
|
|
4523
4750
|
if (autoSaveKey === void 0 || typeof globalThis.localStorage === "undefined") return;
|
|
4524
4751
|
const loadIdentity = `${autoSaveKey}:${form.schema.id}:${form.schema.version}`;
|
|
4525
4752
|
if (loadedDraftKey.current === loadIdentity) return;
|
|
@@ -4531,7 +4758,7 @@ function ContextFormRenderer({
|
|
|
4531
4758
|
form.restoreValues(draft.values);
|
|
4532
4759
|
setDraftRestored(true);
|
|
4533
4760
|
}, [autoSaveKey, form.restoreValues, form.schema.id, form.schema.version]);
|
|
4534
|
-
(0,
|
|
4761
|
+
(0, import_react8.useEffect)(() => {
|
|
4535
4762
|
if (form.submitStatus === "success") return;
|
|
4536
4763
|
const timeout = globalThis.setTimeout(() => {
|
|
4537
4764
|
onDraftSave?.(form.values);
|
|
@@ -4587,7 +4814,7 @@ function ContextFormRenderer({
|
|
|
4587
4814
|
if (rendererSubmissionInFlight.current || submitState === "submitting" || submitState === "success" || confirmation !== null && !guardsConfirmed) {
|
|
4588
4815
|
return { status: "cancelled" };
|
|
4589
4816
|
}
|
|
4590
|
-
const validation = (0,
|
|
4817
|
+
const validation = (0, import_core7.validateAnswers)(form.schema, form.values);
|
|
4591
4818
|
const firstInvalidFieldId = validation.issues[0]?.fieldId;
|
|
4592
4819
|
if (validation.valid && !guardsConfirmed) {
|
|
4593
4820
|
rendererSubmissionInFlight.current = true;
|
|
@@ -4650,8 +4877,9 @@ function ContextFormRenderer({
|
|
|
4650
4877
|
return result;
|
|
4651
4878
|
}
|
|
4652
4879
|
if (result.status === "error") {
|
|
4653
|
-
|
|
4654
|
-
|
|
4880
|
+
const payload = result.error instanceof import_core7.FormSubmissionError ? result.error.payload : (0, import_core7.isFormSubmissionSerializedError)(result.error) ? result.error : void 0;
|
|
4881
|
+
if (payload !== void 0) {
|
|
4882
|
+
const fieldErrors = payload.fieldErrors ?? {};
|
|
4655
4883
|
form.setServerErrors?.(fieldErrors);
|
|
4656
4884
|
const firstServerFieldId = form.schema.fields.find((field) => Object.hasOwn(fieldErrors, field.id))?.id ?? Object.keys(fieldErrors)[0];
|
|
4657
4885
|
if (firstServerFieldId !== void 0) {
|
|
@@ -4659,6 +4887,9 @@ function ContextFormRenderer({
|
|
|
4659
4887
|
if (invalidPageIndex !== void 0 && invalidPageIndex >= 0) setCurrentPageIndex(invalidPageIndex);
|
|
4660
4888
|
focusFirstIssue(firstServerFieldId);
|
|
4661
4889
|
}
|
|
4890
|
+
if (payload.piiFindings !== void 0 && payload.piiFindings.length > 0) {
|
|
4891
|
+
setConfirmation({ findings: payload.piiFindings, generic: false });
|
|
4892
|
+
}
|
|
4662
4893
|
}
|
|
4663
4894
|
return result;
|
|
4664
4895
|
}
|
|
@@ -4889,7 +5120,7 @@ function ContextFormRenderer({
|
|
|
4889
5120
|
...slots.renderCharacterCount === void 0 ? {} : { renderCharacterCount: slots.renderCharacterCount }
|
|
4890
5121
|
};
|
|
4891
5122
|
if (slots.renderField !== void 0) {
|
|
4892
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
5123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react8.Fragment, { children: slots.renderField({
|
|
4893
5124
|
question: field,
|
|
4894
5125
|
value: form.values[field.id],
|
|
4895
5126
|
onChange: (value) => {
|
|
@@ -4960,8 +5191,8 @@ function ContextFormRenderer({
|
|
|
4960
5191
|
] }),
|
|
4961
5192
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "fe-status", "aria-live": "polite", children: [
|
|
4962
5193
|
form.submitStatus === "success" ? completionRegion : null,
|
|
4963
|
-
form.submitStatus === "error" && form.submitError !== null ? slots.renderSubmitError?.({ error: form.submitError, onRetry: () => void submitValues() }) ?? (form.submitError instanceof FormSubmissionError && form.submitError.payload.
|
|
4964
|
-
form.submitError.payload.
|
|
5194
|
+
form.submitStatus === "error" && form.submitError !== null ? slots.renderSubmitError?.({ error: form.submitError, onRetry: () => void submitValues() }) ?? (form.submitError instanceof import_core7.FormSubmissionError && (form.submitError.payload.formErrors?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { role: "alert", children: [
|
|
5195
|
+
form.submitError.payload.formErrors?.map((message) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: message }, message)),
|
|
4965
5196
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: () => void submitValues(), children: resolveMessage("retryButton") })
|
|
4966
5197
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { role: "alert", children: [
|
|
4967
5198
|
errorMessageKey === void 0 ? resolveMessage("serverErrorSummary") : form.translate(errorMessageKey),
|
|
@@ -5017,7 +5248,7 @@ var defaultRendererTranslator = {
|
|
|
5017
5248
|
};
|
|
5018
5249
|
function FormRenderer(props) {
|
|
5019
5250
|
const i18n = useFormEngineI18n();
|
|
5020
|
-
const isProviderValue = (0,
|
|
5251
|
+
const isProviderValue = (0, import_react8.useContext)(FormEngineI18nProviderScopeContext);
|
|
5021
5252
|
if (!("schema" in props)) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ContextFormRenderer, { ...props });
|
|
5022
5253
|
const {
|
|
5023
5254
|
schema,
|
|
@@ -5044,6 +5275,9 @@ function FormRenderer(props) {
|
|
|
5044
5275
|
}
|
|
5045
5276
|
);
|
|
5046
5277
|
}
|
|
5278
|
+
|
|
5279
|
+
// src/types.ts
|
|
5280
|
+
var import_core8 = require("@form-engine-ts/core");
|
|
5047
5281
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5048
5282
|
0 && (module.exports = {
|
|
5049
5283
|
BUILDER_TRANSLATION_ALIASES,
|
|
@@ -5068,6 +5302,7 @@ function FormRenderer(props) {
|
|
|
5068
5302
|
useFormBuilder,
|
|
5069
5303
|
useFormEngineI18n,
|
|
5070
5304
|
useSubmissionReceipts,
|
|
5305
|
+
useTranslationComparison,
|
|
5071
5306
|
useTranslationWorkspace,
|
|
5072
5307
|
validateLocalePipeline
|
|
5073
5308
|
});
|