@form-engine-ts/react 2.9.4 → 2.9.6
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 +20 -3
- package/dist/index.cjs +377 -143
- package/dist/index.d.cts +67 -7
- package/dist/index.d.ts +67 -7
- package/dist/index.js +377 -143
- package/dist/styles.css +17 -0
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(index_exports, {
|
|
|
23
23
|
FormBuilder: () => FormBuilder,
|
|
24
24
|
FormProvider: () => FormProvider,
|
|
25
25
|
FormRenderer: () => FormRenderer,
|
|
26
|
+
FormSubmissionError: () => FormSubmissionError,
|
|
26
27
|
createLocalStorageSubmissionAttemptStore: () => createLocalStorageSubmissionAttemptStore,
|
|
27
28
|
createLocalStorageSubmissionReceiptStore: () => createLocalStorageSubmissionReceiptStore,
|
|
28
29
|
resolveInitialFieldType: () => resolveInitialFieldType,
|
|
@@ -1088,7 +1089,7 @@ function BuilderButton(props) {
|
|
|
1088
1089
|
...props,
|
|
1089
1090
|
className: primitiveClassName(props.className, "feb-button", context.unstyled),
|
|
1090
1091
|
disabled: context.readOnly || props.disabled === true,
|
|
1091
|
-
readOnly: context.readOnly
|
|
1092
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1092
1093
|
}
|
|
1093
1094
|
);
|
|
1094
1095
|
}
|
|
@@ -1103,7 +1104,7 @@ function BuilderIconButton(props) {
|
|
|
1103
1104
|
icon,
|
|
1104
1105
|
className: primitiveClassName(props.className, "feb-icon-button", context.unstyled),
|
|
1105
1106
|
disabled: context.readOnly || props.disabled === true,
|
|
1106
|
-
readOnly: context.readOnly
|
|
1107
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1107
1108
|
}
|
|
1108
1109
|
);
|
|
1109
1110
|
}
|
|
@@ -1116,7 +1117,7 @@ function BuilderTextInput(props) {
|
|
|
1116
1117
|
...props,
|
|
1117
1118
|
className: primitiveClassName(props.className, "feb-input", context.unstyled),
|
|
1118
1119
|
disabled: context.readOnly || props.disabled === true,
|
|
1119
|
-
readOnly: context.readOnly
|
|
1120
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1120
1121
|
}
|
|
1121
1122
|
);
|
|
1122
1123
|
}
|
|
@@ -1129,7 +1130,7 @@ function BuilderTextArea(props) {
|
|
|
1129
1130
|
...props,
|
|
1130
1131
|
className: primitiveClassName(props.className, "feb-textarea", context.unstyled),
|
|
1131
1132
|
disabled: context.readOnly || props.disabled === true,
|
|
1132
|
-
readOnly: context.readOnly
|
|
1133
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1133
1134
|
}
|
|
1134
1135
|
);
|
|
1135
1136
|
}
|
|
@@ -1142,7 +1143,7 @@ function BuilderSelect(props) {
|
|
|
1142
1143
|
...props,
|
|
1143
1144
|
className: primitiveClassName(props.className, "feb-select", context.unstyled),
|
|
1144
1145
|
disabled: context.readOnly || props.disabled === true,
|
|
1145
|
-
readOnly: context.readOnly
|
|
1146
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1146
1147
|
}
|
|
1147
1148
|
);
|
|
1148
1149
|
}
|
|
@@ -1155,7 +1156,7 @@ function BuilderCheckbox(props) {
|
|
|
1155
1156
|
...props,
|
|
1156
1157
|
className: primitiveClassName(props.className, "feb-checkbox", context.unstyled),
|
|
1157
1158
|
disabled: context.readOnly || props.disabled === true,
|
|
1158
|
-
readOnly: context.readOnly
|
|
1159
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1159
1160
|
}
|
|
1160
1161
|
);
|
|
1161
1162
|
}
|
|
@@ -1301,6 +1302,59 @@ function fieldTypeKey(type) {
|
|
|
1301
1302
|
function operatorKey(operator) {
|
|
1302
1303
|
return `builder.operator.${operator}`;
|
|
1303
1304
|
}
|
|
1305
|
+
function manualTranslationContext(schema, locale, target, property, translatedText) {
|
|
1306
|
+
if (target.kind === "form") {
|
|
1307
|
+
if (property !== "title" && property !== "description" && property !== "completionMessage") return void 0;
|
|
1308
|
+
return {
|
|
1309
|
+
locale,
|
|
1310
|
+
kind: "form",
|
|
1311
|
+
nodeId: schema.id,
|
|
1312
|
+
property,
|
|
1313
|
+
sourceText: schema[property] ?? "",
|
|
1314
|
+
translatedText,
|
|
1315
|
+
...schema.translationMetadata?.[locale]?.[property] === void 0 ? {} : { existingTranslationMetadata: schema.translationMetadata[locale]?.[property] }
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
if (target.id === void 0) return void 0;
|
|
1319
|
+
if (target.kind === "field") {
|
|
1320
|
+
const field = schema.fields.find((candidate) => candidate.id === target.id);
|
|
1321
|
+
if (field === void 0 || property !== "title" && property !== "description") return void 0;
|
|
1322
|
+
return {
|
|
1323
|
+
locale,
|
|
1324
|
+
kind: "field",
|
|
1325
|
+
nodeId: field.id,
|
|
1326
|
+
property,
|
|
1327
|
+
sourceText: field[property] ?? "",
|
|
1328
|
+
translatedText,
|
|
1329
|
+
...field.translationMetadata?.[locale]?.[property] === void 0 ? {} : { existingTranslationMetadata: field.translationMetadata[locale]?.[property] }
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
if (target.kind === "page") {
|
|
1333
|
+
const page = schema.pages?.find((candidate) => candidate.id === target.id);
|
|
1334
|
+
if (page === void 0 || property !== "title" && property !== "description") return void 0;
|
|
1335
|
+
return {
|
|
1336
|
+
locale,
|
|
1337
|
+
kind: "page",
|
|
1338
|
+
nodeId: page.id,
|
|
1339
|
+
property,
|
|
1340
|
+
sourceText: page[property] ?? "",
|
|
1341
|
+
translatedText,
|
|
1342
|
+
...page.translationMetadata?.[locale]?.[property] === void 0 ? {} : { existingTranslationMetadata: page.translationMetadata[locale]?.[property] }
|
|
1343
|
+
};
|
|
1344
|
+
}
|
|
1345
|
+
if (property !== "label") return void 0;
|
|
1346
|
+
const option = schema.fields.filter((field) => "options" in field).flatMap((field) => field.options).find((candidate) => candidate.id === target.id);
|
|
1347
|
+
if (option === void 0) return void 0;
|
|
1348
|
+
return {
|
|
1349
|
+
locale,
|
|
1350
|
+
kind: "option",
|
|
1351
|
+
nodeId: option.id,
|
|
1352
|
+
property,
|
|
1353
|
+
sourceText: option.label,
|
|
1354
|
+
translatedText,
|
|
1355
|
+
...option.translationMetadata?.[locale]?.[property] === void 0 ? {} : { existingTranslationMetadata: option.translationMetadata[locale]?.[property] }
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1304
1358
|
function defaultConditionValue(field) {
|
|
1305
1359
|
if (field.type === "checkbox") return true;
|
|
1306
1360
|
if (field.type === "number" || field.type === "rating") return field.min ?? 1;
|
|
@@ -1559,25 +1613,30 @@ function FormBuilder({
|
|
|
1559
1613
|
setIsTranslating(false);
|
|
1560
1614
|
}
|
|
1561
1615
|
};
|
|
1562
|
-
const
|
|
1563
|
-
if (readOnly) return;
|
|
1564
|
-
const
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1616
|
+
const setManualTranslation = (targetLocale, target, property, text) => {
|
|
1617
|
+
if (readOnly) return { success: true };
|
|
1618
|
+
const normalizedLocale = targetLocale.trim();
|
|
1619
|
+
const context = manualTranslationContext(schema, normalizedLocale, target, property, text);
|
|
1620
|
+
const metadata = context === void 0 ? void 0 : createManualTranslationMetadata?.(context);
|
|
1621
|
+
return executeAction(
|
|
1567
1622
|
() => headless.setLocaleTranslation(
|
|
1568
|
-
|
|
1623
|
+
normalizedLocale,
|
|
1569
1624
|
target,
|
|
1570
|
-
|
|
1571
|
-
|
|
1625
|
+
property,
|
|
1626
|
+
text,
|
|
1572
1627
|
metadata === void 0 ? void 0 : { metadata }
|
|
1573
1628
|
),
|
|
1574
1629
|
{
|
|
1575
|
-
action: "
|
|
1576
|
-
targetId:
|
|
1577
|
-
params: { locale:
|
|
1630
|
+
action: "setManualTranslation",
|
|
1631
|
+
...target.id === void 0 ? {} : { targetId: target.id },
|
|
1632
|
+
params: { locale: normalizedLocale, kind: target.kind, property }
|
|
1578
1633
|
}
|
|
1579
1634
|
);
|
|
1580
1635
|
};
|
|
1636
|
+
const updateManualTranslation = (context) => {
|
|
1637
|
+
const target = context.kind === "form" ? { kind: "form" } : { kind: context.kind, id: context.nodeId };
|
|
1638
|
+
setManualTranslation(context.locale, target, context.property, context.translatedText);
|
|
1639
|
+
};
|
|
1581
1640
|
const updateFormTranslation = (property, translatedText) => {
|
|
1582
1641
|
if (editingLocale.length === 0) return;
|
|
1583
1642
|
updateManualTranslation({
|
|
@@ -1686,6 +1745,7 @@ function FormBuilder({
|
|
|
1686
1745
|
...target.id === void 0 ? {} : { targetId: target.id },
|
|
1687
1746
|
params: { locale: targetLocale, property }
|
|
1688
1747
|
}),
|
|
1748
|
+
setManualTranslation,
|
|
1689
1749
|
addLocale: (targetLocale) => executeAction(() => headless.addLocale(targetLocale), {
|
|
1690
1750
|
action: "addLocale",
|
|
1691
1751
|
params: { locale: targetLocale }
|
|
@@ -2598,6 +2658,17 @@ function FormProvider({
|
|
|
2598
2658
|
},
|
|
2599
2659
|
[validSchema, validationPageIndex]
|
|
2600
2660
|
);
|
|
2661
|
+
const setServerErrors = (0, import_react3.useCallback)((fieldErrors) => {
|
|
2662
|
+
setErrors(
|
|
2663
|
+
Object.fromEntries(
|
|
2664
|
+
Object.entries(fieldErrors).map(([fieldId, message]) => [
|
|
2665
|
+
fieldId,
|
|
2666
|
+
{ fieldId, code: "invalid_type", messageKey: message, params: {} }
|
|
2667
|
+
])
|
|
2668
|
+
)
|
|
2669
|
+
);
|
|
2670
|
+
setValidationPageIndex(null);
|
|
2671
|
+
}, []);
|
|
2601
2672
|
const restoreValues = (0, import_react3.useCallback)(
|
|
2602
2673
|
(restoredValues) => {
|
|
2603
2674
|
const fieldIds = new Set(validSchema.fields.map((field) => field.id));
|
|
@@ -2682,6 +2753,7 @@ function FormProvider({
|
|
|
2682
2753
|
submitError,
|
|
2683
2754
|
isSubmitting: submitStatus === "submitting",
|
|
2684
2755
|
setValue,
|
|
2756
|
+
setServerErrors,
|
|
2685
2757
|
restoreValues,
|
|
2686
2758
|
validatePage,
|
|
2687
2759
|
reset,
|
|
@@ -2695,6 +2767,7 @@ function FormProvider({
|
|
|
2695
2767
|
reset,
|
|
2696
2768
|
restoreValues,
|
|
2697
2769
|
setValue,
|
|
2770
|
+
setServerErrors,
|
|
2698
2771
|
submit,
|
|
2699
2772
|
submitError,
|
|
2700
2773
|
submitStatus,
|
|
@@ -2841,6 +2914,18 @@ function useSubmissionReceipts(store, queries) {
|
|
|
2841
2914
|
// src/renderer.tsx
|
|
2842
2915
|
var import_core4 = require("@form-engine-ts/core");
|
|
2843
2916
|
var import_react5 = require("react");
|
|
2917
|
+
|
|
2918
|
+
// src/types.ts
|
|
2919
|
+
var FormSubmissionError = class extends Error {
|
|
2920
|
+
payload;
|
|
2921
|
+
constructor(message, payload) {
|
|
2922
|
+
super(message);
|
|
2923
|
+
this.name = "FormSubmissionError";
|
|
2924
|
+
this.payload = payload ?? { formError: message };
|
|
2925
|
+
}
|
|
2926
|
+
};
|
|
2927
|
+
|
|
2928
|
+
// src/renderer.tsx
|
|
2844
2929
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
2845
2930
|
function describedBy(field, error, helpId, errorId) {
|
|
2846
2931
|
const ids = [field.description === void 0 ? void 0 : helpId, error === void 0 ? void 0 : errorId].filter(
|
|
@@ -3037,6 +3122,30 @@ function isRecord(value) {
|
|
|
3037
3122
|
function isFormValue(value) {
|
|
3038
3123
|
return value === void 0 || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value) || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
3039
3124
|
}
|
|
3125
|
+
function displaySubmittedValue(field, value, translate) {
|
|
3126
|
+
if (value === void 0 || value === null) return "";
|
|
3127
|
+
if (field.type === "checkbox") return value === true ? translate("form.yes") : translate("form.no");
|
|
3128
|
+
if (field.type === "multi-select" && Array.isArray(value)) {
|
|
3129
|
+
const labels = new Map(field.options.map((option) => [option.id, option.label]));
|
|
3130
|
+
return value.map((item) => labels.get(item) ?? item).join(", ");
|
|
3131
|
+
}
|
|
3132
|
+
if ((field.type === "radio" || field.type === "select") && typeof value === "string") {
|
|
3133
|
+
return field.options.find((option) => option.id === value)?.label ?? value;
|
|
3134
|
+
}
|
|
3135
|
+
if (Array.isArray(value)) return value.join(", ");
|
|
3136
|
+
return String(value);
|
|
3137
|
+
}
|
|
3138
|
+
function buildSubmittedItems(schema, answers, visibility, translate, showHiddenFields) {
|
|
3139
|
+
return schema.fields.filter((field) => showHiddenFields || visibility[field.id] === true).map((field) => ({
|
|
3140
|
+
fieldId: field.id,
|
|
3141
|
+
title: field.title,
|
|
3142
|
+
type: field.type,
|
|
3143
|
+
rawValue: answers[field.id],
|
|
3144
|
+
displayValue: displaySubmittedValue(field, answers[field.id], translate),
|
|
3145
|
+
visible: visibility[field.id] === true,
|
|
3146
|
+
...field.metadata === void 0 ? {} : { metadata: field.metadata }
|
|
3147
|
+
}));
|
|
3148
|
+
}
|
|
3040
3149
|
function parseDraft(serialized) {
|
|
3041
3150
|
try {
|
|
3042
3151
|
const value = JSON.parse(serialized);
|
|
@@ -3063,6 +3172,11 @@ function ContextFormRenderer({
|
|
|
3063
3172
|
autoSaveKey,
|
|
3064
3173
|
beforeSubmit,
|
|
3065
3174
|
onDraftSave,
|
|
3175
|
+
successRenderMode = "append",
|
|
3176
|
+
submissionConfirmationRenderMode = "inline",
|
|
3177
|
+
showHiddenFieldsInSummary = false,
|
|
3178
|
+
fieldsClassName,
|
|
3179
|
+
hideFormOnSuccess = false,
|
|
3066
3180
|
submissionGuards = [],
|
|
3067
3181
|
receiptStore,
|
|
3068
3182
|
attemptStore,
|
|
@@ -3078,9 +3192,13 @@ function ContextFormRenderer({
|
|
|
3078
3192
|
const [focusFieldId, setFocusFieldId] = (0, import_react5.useState)(null);
|
|
3079
3193
|
const [confirmation, setConfirmation] = (0, import_react5.useState)(null);
|
|
3080
3194
|
const [guardMessage, setGuardMessage] = (0, import_react5.useState)(null);
|
|
3195
|
+
const [guardsPending, setGuardsPending] = (0, import_react5.useState)(false);
|
|
3081
3196
|
const [receipt, setReceipt] = (0, import_react5.useState)(null);
|
|
3197
|
+
const [completionData, setCompletionData] = (0, import_react5.useState)(null);
|
|
3082
3198
|
const [receiptLoaded, setReceiptLoaded] = (0, import_react5.useState)(receiptStore === void 0);
|
|
3083
3199
|
const rendererSubmissionInFlight = (0, import_react5.useRef)(false);
|
|
3200
|
+
const completionRef = (0, import_react5.useRef)(null);
|
|
3201
|
+
const confirmationRef = (0, import_react5.useRef)(null);
|
|
3084
3202
|
const pages = form.schema.pages;
|
|
3085
3203
|
const visiblePageIndexes = (0, import_react5.useMemo)(
|
|
3086
3204
|
() => pages === void 0 ? [] : pages.flatMap((page, index) => form.pageVisibility[page.id] === true ? [index] : []),
|
|
@@ -3090,8 +3208,13 @@ function ContextFormRenderer({
|
|
|
3090
3208
|
const activeVisibleIndex = visiblePageIndexes.indexOf(currentPageIndex);
|
|
3091
3209
|
const fieldIds = activePage === void 0 ? void 0 : new Set(activePage.questionIds);
|
|
3092
3210
|
const visibleValues = (0, import_react5.useMemo)(() => (0, import_core4.selectVisibleAnswers)(form.schema, form.values), [form.schema, form.values]);
|
|
3093
|
-
const submitState = confirmation === null ? form.submitStatus : "confirming";
|
|
3211
|
+
const submitState = confirmation === null && !guardsPending ? form.submitStatus : "confirming";
|
|
3094
3212
|
const interactionLocked = submitState === "confirming" || submitState === "submitting";
|
|
3213
|
+
const isReplaceMode = successRenderMode === "replace" || hideFormOnSuccess;
|
|
3214
|
+
const focusSubmitButton = (0, import_react5.useCallback)(() => {
|
|
3215
|
+
const button = formRef.current?.querySelector(".fe-submit, button[type='submit'], button");
|
|
3216
|
+
button?.focus();
|
|
3217
|
+
}, []);
|
|
3095
3218
|
(0, import_react5.useEffect)(() => {
|
|
3096
3219
|
let active = true;
|
|
3097
3220
|
if (receiptStore === void 0) {
|
|
@@ -3131,6 +3254,25 @@ function ContextFormRenderer({
|
|
|
3131
3254
|
setFocusFieldId(null);
|
|
3132
3255
|
}
|
|
3133
3256
|
}, [focusFieldId]);
|
|
3257
|
+
(0, import_react5.useEffect)(() => {
|
|
3258
|
+
if (!isReplaceMode || form.submitStatus !== "success") return;
|
|
3259
|
+
completionRef.current?.focus();
|
|
3260
|
+
}, [form.submitStatus, isReplaceMode]);
|
|
3261
|
+
(0, import_react5.useEffect)(() => {
|
|
3262
|
+
if (confirmation === null) return;
|
|
3263
|
+
const confirmButton = confirmationRef.current?.querySelector("[data-fe-confirm], button");
|
|
3264
|
+
confirmButton?.focus();
|
|
3265
|
+
if (submissionConfirmationRenderMode !== "dialog") return;
|
|
3266
|
+
const onKeyDown = (event) => {
|
|
3267
|
+
if (event.key === "Escape") {
|
|
3268
|
+
event.preventDefault();
|
|
3269
|
+
setConfirmation(null);
|
|
3270
|
+
globalThis.setTimeout(focusSubmitButton, 0);
|
|
3271
|
+
}
|
|
3272
|
+
};
|
|
3273
|
+
globalThis.addEventListener("keydown", onKeyDown);
|
|
3274
|
+
return () => globalThis.removeEventListener("keydown", onKeyDown);
|
|
3275
|
+
}, [confirmation, focusSubmitButton, submissionConfirmationRenderMode]);
|
|
3134
3276
|
(0, import_react5.useEffect)(() => {
|
|
3135
3277
|
if (autoSaveKey === void 0 || typeof globalThis.localStorage === "undefined") return;
|
|
3136
3278
|
const loadIdentity = `${autoSaveKey}:${form.schema.id}:${form.schema.version}`;
|
|
@@ -3196,13 +3338,14 @@ function ContextFormRenderer({
|
|
|
3196
3338
|
};
|
|
3197
3339
|
};
|
|
3198
3340
|
const submitValues = async (guardsConfirmed = false) => {
|
|
3199
|
-
if (rendererSubmissionInFlight.current || confirmation !== null && !guardsConfirmed) {
|
|
3341
|
+
if (rendererSubmissionInFlight.current || submitState === "submitting" || submitState === "success" || confirmation !== null && !guardsConfirmed) {
|
|
3200
3342
|
return { status: "cancelled" };
|
|
3201
3343
|
}
|
|
3202
3344
|
const validation = (0, import_core4.validateAnswers)(form.schema, form.values);
|
|
3203
3345
|
const firstInvalidFieldId = validation.issues[0]?.fieldId;
|
|
3204
3346
|
if (validation.valid && !guardsConfirmed && submissionGuards.length > 0) {
|
|
3205
3347
|
rendererSubmissionInFlight.current = true;
|
|
3348
|
+
setGuardsPending(true);
|
|
3206
3349
|
try {
|
|
3207
3350
|
const guardResult = await runSubmissionGuards(submissionGuards);
|
|
3208
3351
|
if (guardResult.status === "block") {
|
|
@@ -3219,6 +3362,7 @@ function ContextFormRenderer({
|
|
|
3219
3362
|
}
|
|
3220
3363
|
} finally {
|
|
3221
3364
|
rendererSubmissionInFlight.current = false;
|
|
3365
|
+
setGuardsPending(false);
|
|
3222
3366
|
}
|
|
3223
3367
|
}
|
|
3224
3368
|
setGuardMessage(null);
|
|
@@ -3244,7 +3388,33 @@ function ContextFormRenderer({
|
|
|
3244
3388
|
focusFirstIssue(firstInvalidFieldId);
|
|
3245
3389
|
return result;
|
|
3246
3390
|
}
|
|
3391
|
+
if (result.status === "error") {
|
|
3392
|
+
if (result.error instanceof FormSubmissionError) {
|
|
3393
|
+
const fieldErrors = result.error.payload.fieldErrors ?? {};
|
|
3394
|
+
form.setServerErrors?.(fieldErrors);
|
|
3395
|
+
const firstServerFieldId = Object.keys(fieldErrors)[0];
|
|
3396
|
+
if (firstServerFieldId !== void 0) {
|
|
3397
|
+
const invalidPageIndex = pages?.findIndex((page) => page.questionIds.includes(firstServerFieldId));
|
|
3398
|
+
if (invalidPageIndex !== void 0 && invalidPageIndex >= 0) setCurrentPageIndex(invalidPageIndex);
|
|
3399
|
+
focusFirstIssue(firstServerFieldId);
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
return result;
|
|
3403
|
+
}
|
|
3247
3404
|
if (result.status !== "success") return result;
|
|
3405
|
+
const submittedAnswers = { ...form.values };
|
|
3406
|
+
const submittedItems = buildSubmittedItems(
|
|
3407
|
+
form.schema,
|
|
3408
|
+
submittedAnswers,
|
|
3409
|
+
form.visibility,
|
|
3410
|
+
(key) => form.translate(key),
|
|
3411
|
+
showHiddenFieldsInSummary
|
|
3412
|
+
);
|
|
3413
|
+
setCompletionData({
|
|
3414
|
+
answers: submittedAnswers,
|
|
3415
|
+
submittedItems,
|
|
3416
|
+
...result.response === void 0 ? {} : { response: result.response }
|
|
3417
|
+
});
|
|
3248
3418
|
if (receiptStore !== void 0) {
|
|
3249
3419
|
const response = result.response;
|
|
3250
3420
|
const submissionId = response?.submissionId ?? submissionAttempt?.attemptId;
|
|
@@ -3256,7 +3426,6 @@ function ContextFormRenderer({
|
|
|
3256
3426
|
};
|
|
3257
3427
|
try {
|
|
3258
3428
|
await receiptStore.save(storedReceipt);
|
|
3259
|
-
setReceipt(storedReceipt);
|
|
3260
3429
|
} catch (cause) {
|
|
3261
3430
|
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
3262
3431
|
try {
|
|
@@ -3283,7 +3452,7 @@ function ContextFormRenderer({
|
|
|
3283
3452
|
};
|
|
3284
3453
|
const handleSubmit = (event) => {
|
|
3285
3454
|
event.preventDefault();
|
|
3286
|
-
if (
|
|
3455
|
+
if (submitState === "submitting" || submitState === "confirming" || submitState === "success") return;
|
|
3287
3456
|
void submitValues();
|
|
3288
3457
|
};
|
|
3289
3458
|
const confirmSubmission = () => {
|
|
@@ -3292,6 +3461,7 @@ function ContextFormRenderer({
|
|
|
3292
3461
|
};
|
|
3293
3462
|
const cancelSubmission = () => {
|
|
3294
3463
|
setConfirmation(null);
|
|
3464
|
+
globalThis.setTimeout(focusSubmitButton, 0);
|
|
3295
3465
|
};
|
|
3296
3466
|
const resetReceipt = async () => {
|
|
3297
3467
|
if (receiptStore === void 0) return;
|
|
@@ -3302,7 +3472,58 @@ function ContextFormRenderer({
|
|
|
3302
3472
|
const validationIssues = Object.values(form.errors).filter((issue) => issue !== void 0);
|
|
3303
3473
|
const canPrev = pages !== void 0 && activeVisibleIndex > 0;
|
|
3304
3474
|
const canNext = pages !== void 0 && activeVisibleIndex < visiblePageIndexes.length - 1;
|
|
3305
|
-
const renderSubmitButton = () =>
|
|
3475
|
+
const renderSubmitButton = () => {
|
|
3476
|
+
const submitButtonProps = {
|
|
3477
|
+
isSubmitting: submitState === "submitting",
|
|
3478
|
+
submitStatus: submitState,
|
|
3479
|
+
disabled: interactionLocked || submitState === "success",
|
|
3480
|
+
onSubmit: () => void submitValues()
|
|
3481
|
+
};
|
|
3482
|
+
return slots.renderSubmitButton?.(submitButtonProps) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "fe-submit", type: "submit", disabled: submitButtonProps.disabled, children: form.translate(form.schema.submitLabelKey ?? "form.submit") });
|
|
3483
|
+
};
|
|
3484
|
+
const completionMessage = form.schema.completionMessage ?? (successMessageKey === void 0 ? "Submitted." : form.translate(successMessageKey));
|
|
3485
|
+
const activeCompletionData = completionData ?? {
|
|
3486
|
+
answers: { ...form.values },
|
|
3487
|
+
submittedItems: buildSubmittedItems(
|
|
3488
|
+
form.schema,
|
|
3489
|
+
form.values,
|
|
3490
|
+
form.visibility,
|
|
3491
|
+
(key) => form.translate(key),
|
|
3492
|
+
showHiddenFieldsInSummary
|
|
3493
|
+
)
|
|
3494
|
+
};
|
|
3495
|
+
const completionProps = {
|
|
3496
|
+
message: completionMessage,
|
|
3497
|
+
schema: form.schema,
|
|
3498
|
+
answers: activeCompletionData.answers,
|
|
3499
|
+
submittedItems: activeCompletionData.submittedItems,
|
|
3500
|
+
...activeCompletionData.response === void 0 ? {} : { response: activeCompletionData.response },
|
|
3501
|
+
onReset: form.reset
|
|
3502
|
+
};
|
|
3503
|
+
const completionRegion = /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ref: completionRef, className: "fe-completion", role: "status", "aria-live": "polite", tabIndex: -1, children: [
|
|
3504
|
+
slots.renderCompletion?.(completionProps) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: completionMessage }),
|
|
3505
|
+
slots.renderSubmittedValues?.({ items: activeCompletionData.submittedItems, schema: form.schema })
|
|
3506
|
+
] });
|
|
3507
|
+
const confirmationContent = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3508
|
+
"div",
|
|
3509
|
+
{
|
|
3510
|
+
ref: confirmationRef,
|
|
3511
|
+
className: "fe-submission-confirmation",
|
|
3512
|
+
role: submissionConfirmationRenderMode === "dialog" ? void 0 : "dialog",
|
|
3513
|
+
children: slots.renderSubmissionConfirmation?.({
|
|
3514
|
+
findings: confirmation?.findings ?? [],
|
|
3515
|
+
message: confirmation?.message ?? form.translate("form.confirmSensitiveData"),
|
|
3516
|
+
schema: form.schema,
|
|
3517
|
+
visibleValues,
|
|
3518
|
+
onConfirm: confirmSubmission,
|
|
3519
|
+
onCancel: cancelSubmission
|
|
3520
|
+
}) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3521
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: confirmation?.message ?? form.translate("form.confirmSensitiveData") }),
|
|
3522
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", "data-fe-confirm": "true", onClick: confirmSubmission, children: form.translate("form.confirmSubmission") }),
|
|
3523
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: cancelSubmission, children: form.translate("form.cancelSubmission") })
|
|
3524
|
+
] })
|
|
3525
|
+
}
|
|
3526
|
+
);
|
|
3306
3527
|
if (!receiptLoaded) return null;
|
|
3307
3528
|
if (receipt !== null) {
|
|
3308
3529
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `fe-form fe-already-submitted ${className}`.trim(), children: slots.renderAlreadySubmitted?.({
|
|
@@ -3313,129 +3534,139 @@ function ContextFormRenderer({
|
|
|
3313
3534
|
receiptStore === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: () => void resetReceipt(), children: form.translate("form.submitAnother") })
|
|
3314
3535
|
] }) });
|
|
3315
3536
|
}
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3537
|
+
if (form.submitStatus === "success" && isReplaceMode) {
|
|
3538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `fe-form ${className}`.trim(), children: completionRegion });
|
|
3539
|
+
}
|
|
3540
|
+
if (confirmation !== null && submissionConfirmationRenderMode === "replace") {
|
|
3541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `fe-form ${className}`.trim(), children: confirmationContent });
|
|
3542
|
+
}
|
|
3543
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3544
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3545
|
+
"form",
|
|
3546
|
+
{
|
|
3547
|
+
ref: formRef,
|
|
3548
|
+
className: `fe-form ${className}`.trim(),
|
|
3549
|
+
noValidate: true,
|
|
3550
|
+
onSubmit: handleSubmit,
|
|
3551
|
+
"aria-hidden": confirmation !== null && submissionConfirmationRenderMode === "dialog" ? true : void 0,
|
|
3552
|
+
children: [
|
|
3553
|
+
slots.renderHeader?.({
|
|
3554
|
+
title: form.schema.title,
|
|
3555
|
+
...form.schema.description === void 0 ? {} : { description: form.schema.description }
|
|
3556
|
+
}) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "fe-header", children: [
|
|
3557
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { children: form.schema.title }),
|
|
3558
|
+
form.schema.description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: form.schema.description }),
|
|
3559
|
+
pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fe-progress", children: [
|
|
3560
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3561
|
+
"div",
|
|
3562
|
+
{
|
|
3563
|
+
className: "form-progress-bar",
|
|
3564
|
+
role: "progressbar",
|
|
3565
|
+
"aria-valuemin": 1,
|
|
3566
|
+
"aria-valuemax": visiblePageIndexes.length,
|
|
3567
|
+
"aria-valuenow": activeVisibleIndex + 1,
|
|
3568
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3569
|
+
"div",
|
|
3570
|
+
{
|
|
3571
|
+
className: "form-progress-fill",
|
|
3572
|
+
style: { width: `${(activeVisibleIndex + 1) / visiblePageIndexes.length * 100}%` }
|
|
3573
|
+
}
|
|
3574
|
+
)
|
|
3575
|
+
}
|
|
3576
|
+
),
|
|
3577
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: form.translate("form.step", { current: activeVisibleIndex + 1, total: visiblePageIndexes.length }) })
|
|
3578
|
+
] }),
|
|
3579
|
+
draftRestored ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "form-draft-badge", children: form.translate("form.draftRestored") }) : null
|
|
3580
|
+
] }),
|
|
3581
|
+
activePage === void 0 ? null : slots.renderPageHeader?.({
|
|
3582
|
+
page: activePage,
|
|
3583
|
+
pageIndex: activeVisibleIndex,
|
|
3584
|
+
totalPages: visiblePageIndexes.length
|
|
3585
|
+
}) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fe-page-header", children: [
|
|
3586
|
+
activePage.title === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "fe-page-title", children: activePage.title }),
|
|
3587
|
+
activePage.description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "fe-page-description", children: activePage.description })
|
|
3588
|
+
] }),
|
|
3589
|
+
(() => {
|
|
3590
|
+
const fieldChildren = form.schema.fields.filter((field) => form.visibility[field.id] === true && (fieldIds === void 0 || fieldIds.has(field.id))).map((field) => {
|
|
3591
|
+
const error = form.errors[field.id];
|
|
3592
|
+
const props = {
|
|
3593
|
+
field,
|
|
3594
|
+
value: form.values[field.id],
|
|
3595
|
+
error,
|
|
3596
|
+
setValue: (value) => form.setValue(field.id, value),
|
|
3597
|
+
translate: form.translate,
|
|
3598
|
+
inputId: `${prefix}-${field.id}`,
|
|
3599
|
+
errorId: `${prefix}-${field.id}-error`,
|
|
3600
|
+
helpId: `${prefix}-${field.id}-help`,
|
|
3601
|
+
...slots.renderCharacterCount === void 0 ? {} : { renderCharacterCount: slots.renderCharacterCount }
|
|
3602
|
+
};
|
|
3603
|
+
if (slots.renderField !== void 0) {
|
|
3604
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react5.Fragment, { children: slots.renderField({
|
|
3605
|
+
question: field,
|
|
3606
|
+
value: form.values[field.id],
|
|
3607
|
+
onChange: (value) => {
|
|
3608
|
+
if (isFormValue(value)) form.setValue(field.id, value);
|
|
3609
|
+
},
|
|
3610
|
+
...error === void 0 ? {} : { error }
|
|
3611
|
+
}) }, field.id);
|
|
3337
3612
|
}
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3613
|
+
const Component = components[field.type];
|
|
3614
|
+
return Component === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultField, { ...props }, field.id) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Component, { ...props }, field.id);
|
|
3615
|
+
});
|
|
3616
|
+
const fieldClassName = `fe-fields${fieldsClassName === void 0 ? "" : ` ${fieldsClassName}`}`;
|
|
3617
|
+
return slots.renderFields?.({ children: fieldChildren, className: fieldClassName }) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: fieldClassName, children: fieldChildren });
|
|
3618
|
+
})(),
|
|
3619
|
+
guardMessage === null ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { role: "alert", children: guardMessage }),
|
|
3620
|
+
confirmation !== null && submissionConfirmationRenderMode === "inline" ? confirmationContent : null,
|
|
3621
|
+
validationIssues.length === 0 ? null : slots.renderValidationSummary?.({ issues: validationIssues }) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fe-validation-summary", role: "alert", children: [
|
|
3622
|
+
validationIssues.length,
|
|
3623
|
+
" validation error",
|
|
3624
|
+
validationIssues.length === 1 ? "" : "s",
|
|
3625
|
+
"."
|
|
3626
|
+
] }),
|
|
3627
|
+
pages === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3628
|
+
slots.renderNavigation?.({
|
|
3629
|
+
currentPage: 0,
|
|
3630
|
+
totalPages: 1,
|
|
3631
|
+
canPrev: false,
|
|
3632
|
+
canNext: false,
|
|
3633
|
+
onPrev: () => void 0,
|
|
3634
|
+
onNext: () => void 0
|
|
3635
|
+
}),
|
|
3636
|
+
renderSubmitButton()
|
|
3637
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "form-step-navigation", children: [
|
|
3638
|
+
slots.renderNavigation?.({
|
|
3639
|
+
currentPage: activeVisibleIndex,
|
|
3640
|
+
totalPages: visiblePageIndexes.length,
|
|
3641
|
+
canPrev,
|
|
3642
|
+
canNext,
|
|
3643
|
+
onPrev: () => {
|
|
3644
|
+
if (!interactionLocked) setCurrentPageIndex(visiblePageIndexes[activeVisibleIndex - 1] ?? 0);
|
|
3645
|
+
},
|
|
3646
|
+
onNext: handleNext
|
|
3647
|
+
}) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3648
|
+
canPrev ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3649
|
+
"button",
|
|
3650
|
+
{
|
|
3651
|
+
className: "btn-prev",
|
|
3652
|
+
type: "button",
|
|
3653
|
+
disabled: interactionLocked,
|
|
3654
|
+
onClick: () => setCurrentPageIndex(visiblePageIndexes[activeVisibleIndex - 1] ?? 0),
|
|
3655
|
+
children: form.translate("form.back")
|
|
3656
|
+
}
|
|
3657
|
+
) : null,
|
|
3658
|
+
canNext ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "btn-next", type: "button", disabled: interactionLocked, onClick: handleNext, children: form.translate("form.next") }) : null
|
|
3659
|
+
] }),
|
|
3660
|
+
canNext ? null : renderSubmitButton()
|
|
3661
|
+
] }),
|
|
3662
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fe-status", "aria-live": "polite", children: [
|
|
3663
|
+
form.submitStatus === "success" ? completionRegion : null,
|
|
3664
|
+
form.submitStatus === "error" && form.submitError !== null ? slots.renderSubmitError?.({ error: form.submitError, onRetry: () => void submitValues() }) ?? (form.submitError instanceof FormSubmissionError && form.submitError.payload.formError !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { role: "alert", children: form.submitError.payload.formError }) : errorMessageKey === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { role: "alert", children: form.translate(errorMessageKey) })) : null
|
|
3665
|
+
] })
|
|
3666
|
+
]
|
|
3375
3667
|
}
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
}) }),
|
|
3379
|
-
guardMessage === null ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { role: "alert", children: guardMessage }),
|
|
3380
|
-
confirmation === null ? null : slots.renderSubmissionConfirmation?.({
|
|
3381
|
-
findings: confirmation.findings,
|
|
3382
|
-
message: confirmation.message ?? form.translate("form.confirmSensitiveData"),
|
|
3383
|
-
schema: form.schema,
|
|
3384
|
-
visibleValues,
|
|
3385
|
-
onConfirm: confirmSubmission,
|
|
3386
|
-
onCancel: cancelSubmission
|
|
3387
|
-
}) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fe-submission-confirmation", role: "dialog", "aria-modal": "true", children: [
|
|
3388
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: confirmation.message ?? form.translate("form.confirmSensitiveData") }),
|
|
3389
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: confirmSubmission, children: form.translate("form.confirmSubmission") }),
|
|
3390
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: cancelSubmission, children: form.translate("form.cancelSubmission") })
|
|
3391
|
-
] }),
|
|
3392
|
-
validationIssues.length === 0 ? null : slots.renderValidationSummary?.({ issues: validationIssues }) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fe-validation-summary", role: "alert", children: [
|
|
3393
|
-
validationIssues.length,
|
|
3394
|
-
" validation error",
|
|
3395
|
-
validationIssues.length === 1 ? "" : "s",
|
|
3396
|
-
"."
|
|
3397
|
-
] }),
|
|
3398
|
-
pages === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3399
|
-
slots.renderNavigation?.({
|
|
3400
|
-
currentPage: 0,
|
|
3401
|
-
totalPages: 1,
|
|
3402
|
-
canPrev: false,
|
|
3403
|
-
canNext: false,
|
|
3404
|
-
onPrev: () => void 0,
|
|
3405
|
-
onNext: () => void 0
|
|
3406
|
-
}),
|
|
3407
|
-
renderSubmitButton()
|
|
3408
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "form-step-navigation", children: [
|
|
3409
|
-
slots.renderNavigation?.({
|
|
3410
|
-
currentPage: activeVisibleIndex,
|
|
3411
|
-
totalPages: visiblePageIndexes.length,
|
|
3412
|
-
canPrev,
|
|
3413
|
-
canNext,
|
|
3414
|
-
onPrev: () => {
|
|
3415
|
-
if (!interactionLocked) setCurrentPageIndex(visiblePageIndexes[activeVisibleIndex - 1] ?? 0);
|
|
3416
|
-
},
|
|
3417
|
-
onNext: handleNext
|
|
3418
|
-
}) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3419
|
-
canPrev ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3420
|
-
"button",
|
|
3421
|
-
{
|
|
3422
|
-
className: "btn-prev",
|
|
3423
|
-
type: "button",
|
|
3424
|
-
disabled: interactionLocked,
|
|
3425
|
-
onClick: () => setCurrentPageIndex(visiblePageIndexes[activeVisibleIndex - 1] ?? 0),
|
|
3426
|
-
children: form.translate("form.back")
|
|
3427
|
-
}
|
|
3428
|
-
) : null,
|
|
3429
|
-
canNext ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "btn-next", type: "button", disabled: interactionLocked, onClick: handleNext, children: form.translate("form.next") }) : null
|
|
3430
|
-
] }),
|
|
3431
|
-
canNext ? null : renderSubmitButton()
|
|
3432
|
-
] }),
|
|
3433
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fe-status", "aria-live": "polite", children: [
|
|
3434
|
-
form.submitStatus === "success" ? slots.renderCompletion?.({
|
|
3435
|
-
message: form.schema.completionMessage ?? (successMessageKey === void 0 ? "Submitted." : form.translate(successMessageKey))
|
|
3436
|
-
}) ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { role: "status", children: form.schema.completionMessage ?? (successMessageKey === void 0 ? "Submitted." : form.translate(successMessageKey)) }) : null,
|
|
3437
|
-
form.submitStatus === "error" && form.submitError !== null ? slots.renderSubmitError?.({ error: form.submitError, onRetry: () => void submitValues() }) ?? (errorMessageKey === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { role: "alert", children: form.translate(errorMessageKey) })) : null
|
|
3438
|
-
] })
|
|
3668
|
+
),
|
|
3669
|
+
confirmation !== null && submissionConfirmationRenderMode === "dialog" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fe-confirmation-dialog-backdrop", role: "dialog", "aria-modal": "true", children: confirmationContent }) : null
|
|
3439
3670
|
] });
|
|
3440
3671
|
}
|
|
3441
3672
|
var RENDERER_MESSAGES = {
|
|
@@ -3448,6 +3679,8 @@ var RENDERER_MESSAGES = {
|
|
|
3448
3679
|
"form.confirmSensitiveData": "Sensitive data may be included. Confirm before submitting.",
|
|
3449
3680
|
"form.confirmSubmission": "Confirm submission",
|
|
3450
3681
|
"form.cancelSubmission": "Cancel",
|
|
3682
|
+
"form.yes": "Yes",
|
|
3683
|
+
"form.no": "No",
|
|
3451
3684
|
"form.alreadySubmitted": "Already submitted.",
|
|
3452
3685
|
"form.submitAnother": "Submit another response",
|
|
3453
3686
|
"validation.required": "This field is required."
|
|
@@ -3489,6 +3722,7 @@ function FormRenderer(props) {
|
|
|
3489
3722
|
FormBuilder,
|
|
3490
3723
|
FormProvider,
|
|
3491
3724
|
FormRenderer,
|
|
3725
|
+
FormSubmissionError,
|
|
3492
3726
|
createLocalStorageSubmissionAttemptStore,
|
|
3493
3727
|
createLocalStorageSubmissionReceiptStore,
|
|
3494
3728
|
resolveInitialFieldType,
|