@form-engine-ts/react 2.9.5 → 3.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 +13 -4
- package/dist/index.cjs +458 -145
- package/dist/index.d.cts +74 -5
- package/dist/index.d.ts +74 -5
- package/dist/index.js +458 -145
- package/dist/styles.css +51 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1214,6 +1214,11 @@ var BUILDER_DEFAULTS = {
|
|
|
1214
1214
|
"builder.translating": "Translating\u2026",
|
|
1215
1215
|
"builder.translationLocale": "Translation locale",
|
|
1216
1216
|
"builder.selectLocale": "Select a locale to edit translations.",
|
|
1217
|
+
"builder.localization.selectLocaleToAdd": "Select a locale to add",
|
|
1218
|
+
"builder.localization.noLocalesConfigured": "Translations not configured",
|
|
1219
|
+
"builder.localization.localesConfiguredSummary": "{{count}} locales configured",
|
|
1220
|
+
"builder.localization.allLocalesAdded": "\u3059\u3079\u3066\u306E\u5019\u88DC\u8A00\u8A9E\u304C\u8FFD\u52A0\u6E08\u307F\u3067\u3059",
|
|
1221
|
+
"builder.localization.maxLocalesReached": "\u767B\u9332\u53EF\u80FD\u306A\u6700\u5927\u8A00\u8A9E\u6570\uFF08{{max}}\uFF09\u306B\u9054\u3057\u307E\u3057\u305F",
|
|
1217
1222
|
"builder.translation": "{{locale}} translation",
|
|
1218
1223
|
"builder.translatedFormTitle": "Translated form title",
|
|
1219
1224
|
"builder.translatedFormDescription": "Translated form description",
|
|
@@ -2585,6 +2590,18 @@ import {
|
|
|
2585
2590
|
validatePageAnswers
|
|
2586
2591
|
} from "@form-engine-ts/core";
|
|
2587
2592
|
import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useEffect, useMemo as useMemo2, useRef, useState as useState2 } from "react";
|
|
2593
|
+
|
|
2594
|
+
// src/types.ts
|
|
2595
|
+
var FormSubmissionError = class extends Error {
|
|
2596
|
+
payload;
|
|
2597
|
+
constructor(message, payload) {
|
|
2598
|
+
super(message);
|
|
2599
|
+
this.name = "FormSubmissionError";
|
|
2600
|
+
this.payload = payload ?? { formError: message };
|
|
2601
|
+
}
|
|
2602
|
+
};
|
|
2603
|
+
|
|
2604
|
+
// src/context.tsx
|
|
2588
2605
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
2589
2606
|
var FormContext = createContext2(null);
|
|
2590
2607
|
function issuesByField(issues) {
|
|
@@ -2592,6 +2609,18 @@ function issuesByField(issues) {
|
|
|
2592
2609
|
for (const issue of issues) result[issue.fieldId] ??= issue;
|
|
2593
2610
|
return result;
|
|
2594
2611
|
}
|
|
2612
|
+
function defaultAttemptId2() {
|
|
2613
|
+
const randomUuid = globalThis.crypto?.randomUUID;
|
|
2614
|
+
if (typeof randomUuid === "function") return randomUuid.call(globalThis.crypto);
|
|
2615
|
+
return `attempt-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
2616
|
+
}
|
|
2617
|
+
function isServerErrorPayload(value) {
|
|
2618
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
2619
|
+
const record = value;
|
|
2620
|
+
const fieldErrors = record.fieldErrors;
|
|
2621
|
+
const formError = record.formError;
|
|
2622
|
+
return (Object.hasOwn(record, "fieldErrors") || Object.hasOwn(record, "formError")) && (fieldErrors === void 0 || typeof fieldErrors === "object" && fieldErrors !== null && !Array.isArray(fieldErrors) && Object.values(fieldErrors).every((message) => typeof message === "string")) && (formError === void 0 || typeof formError === "string");
|
|
2623
|
+
}
|
|
2595
2624
|
function FormProvider({
|
|
2596
2625
|
schema,
|
|
2597
2626
|
locale,
|
|
@@ -2635,6 +2664,17 @@ function FormProvider({
|
|
|
2635
2664
|
},
|
|
2636
2665
|
[validSchema, validationPageIndex]
|
|
2637
2666
|
);
|
|
2667
|
+
const setServerErrors = useCallback2((fieldErrors) => {
|
|
2668
|
+
setErrors(
|
|
2669
|
+
Object.fromEntries(
|
|
2670
|
+
Object.entries(fieldErrors).map(([fieldId, message]) => [
|
|
2671
|
+
fieldId,
|
|
2672
|
+
{ fieldId, code: "invalid_type", messageKey: message, params: {} }
|
|
2673
|
+
])
|
|
2674
|
+
)
|
|
2675
|
+
);
|
|
2676
|
+
setValidationPageIndex(null);
|
|
2677
|
+
}, []);
|
|
2638
2678
|
const restoreValues = useCallback2(
|
|
2639
2679
|
(restoredValues) => {
|
|
2640
2680
|
const fieldIds = new Set(validSchema.fields.map((field) => field.id));
|
|
@@ -2665,7 +2705,7 @@ function FormProvider({
|
|
|
2665
2705
|
setSubmitError(null);
|
|
2666
2706
|
}, [initialValues]);
|
|
2667
2707
|
const submit = useCallback2(
|
|
2668
|
-
async (beforeSubmit,
|
|
2708
|
+
async (beforeSubmit, submitContext) => {
|
|
2669
2709
|
if (submissionInFlight.current) return { status: "cancelled" };
|
|
2670
2710
|
const validation = validateAnswers(validSchema, values);
|
|
2671
2711
|
if (!validation.valid) {
|
|
@@ -2686,13 +2726,22 @@ function FormProvider({
|
|
|
2686
2726
|
setSubmitStatus("idle");
|
|
2687
2727
|
return { status: "cancelled" };
|
|
2688
2728
|
}
|
|
2689
|
-
const
|
|
2690
|
-
|
|
2729
|
+
const context = submitContext ?? {
|
|
2730
|
+
attemptId: defaultAttemptId2(),
|
|
2731
|
+
formId: validSchema.id,
|
|
2732
|
+
formVersion: validSchema.version,
|
|
2733
|
+
locale,
|
|
2734
|
+
submittedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2735
|
+
};
|
|
2736
|
+
const response = await onSubmit({ ...visibleValues }, context);
|
|
2691
2737
|
if (resetOnSuccess) setValues({ ...initialValues });
|
|
2692
2738
|
setSubmitStatus("success");
|
|
2693
2739
|
return response === void 0 ? { status: "success" } : { status: "success", response };
|
|
2694
2740
|
} catch (cause) {
|
|
2695
|
-
const error = cause
|
|
2741
|
+
const error = isServerErrorPayload(cause) ? new FormSubmissionError(
|
|
2742
|
+
cause.formError ?? (cause instanceof Error ? cause.message : "Form submission failed."),
|
|
2743
|
+
cause
|
|
2744
|
+
) : cause instanceof Error ? cause : new Error(String(cause));
|
|
2696
2745
|
setSubmitError(error);
|
|
2697
2746
|
setSubmitStatus("error");
|
|
2698
2747
|
return { status: "error", error };
|
|
@@ -2700,7 +2749,7 @@ function FormProvider({
|
|
|
2700
2749
|
submissionInFlight.current = false;
|
|
2701
2750
|
}
|
|
2702
2751
|
},
|
|
2703
|
-
[initialValues, onSubmit, resetOnSuccess, validSchema, values]
|
|
2752
|
+
[initialValues, locale, onSubmit, resetOnSuccess, validSchema, values]
|
|
2704
2753
|
);
|
|
2705
2754
|
const translate = useCallback2(
|
|
2706
2755
|
(key, params) => translator.translate(key, locale, params),
|
|
@@ -2719,6 +2768,7 @@ function FormProvider({
|
|
|
2719
2768
|
submitError,
|
|
2720
2769
|
isSubmitting: submitStatus === "submitting",
|
|
2721
2770
|
setValue,
|
|
2771
|
+
setServerErrors,
|
|
2722
2772
|
restoreValues,
|
|
2723
2773
|
validatePage,
|
|
2724
2774
|
reset,
|
|
@@ -2732,6 +2782,7 @@ function FormProvider({
|
|
|
2732
2782
|
reset,
|
|
2733
2783
|
restoreValues,
|
|
2734
2784
|
setValue,
|
|
2785
|
+
setServerErrors,
|
|
2735
2786
|
submit,
|
|
2736
2787
|
submitError,
|
|
2737
2788
|
submitStatus,
|
|
@@ -2882,6 +2933,7 @@ import {
|
|
|
2882
2933
|
} from "@form-engine-ts/core";
|
|
2883
2934
|
import {
|
|
2884
2935
|
Fragment as Fragment2,
|
|
2936
|
+
useCallback as useCallback3,
|
|
2885
2937
|
useEffect as useEffect3,
|
|
2886
2938
|
useId,
|
|
2887
2939
|
useMemo as useMemo4,
|
|
@@ -3074,7 +3126,11 @@ function DefaultField(props) {
|
|
|
3074
3126
|
fieldId: field.id,
|
|
3075
3127
|
current: typeof value === "string" ? value.length : 0,
|
|
3076
3128
|
max: field.maxLength
|
|
3077
|
-
}) :
|
|
3129
|
+
}) ?? /* @__PURE__ */ jsxs2("div", { className: "fe-character-count", "aria-live": "polite", children: [
|
|
3130
|
+
typeof value === "string" ? value.length : 0,
|
|
3131
|
+
" / ",
|
|
3132
|
+
field.maxLength
|
|
3133
|
+
] }) : null,
|
|
3078
3134
|
/* @__PURE__ */ jsx3(FieldMessage, { props })
|
|
3079
3135
|
] });
|
|
3080
3136
|
}
|
|
@@ -3084,6 +3140,30 @@ function isRecord(value) {
|
|
|
3084
3140
|
function isFormValue(value) {
|
|
3085
3141
|
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");
|
|
3086
3142
|
}
|
|
3143
|
+
function displaySubmittedValue(field, value, translate) {
|
|
3144
|
+
if (value === void 0 || value === null) return "";
|
|
3145
|
+
if (field.type === "checkbox") return value === true ? translate("form.yes") : translate("form.no");
|
|
3146
|
+
if (field.type === "multi-select" && Array.isArray(value)) {
|
|
3147
|
+
const labels = new Map(field.options.map((option) => [option.id, option.label]));
|
|
3148
|
+
return value.map((item) => labels.get(item) ?? item).join(", ");
|
|
3149
|
+
}
|
|
3150
|
+
if ((field.type === "radio" || field.type === "select") && typeof value === "string") {
|
|
3151
|
+
return field.options.find((option) => option.id === value)?.label ?? value;
|
|
3152
|
+
}
|
|
3153
|
+
if (Array.isArray(value)) return value.join(", ");
|
|
3154
|
+
return String(value);
|
|
3155
|
+
}
|
|
3156
|
+
function buildSubmittedItems(schema, answers, visibility, translate, showHiddenFields) {
|
|
3157
|
+
return schema.fields.filter((field) => showHiddenFields || visibility[field.id] === true).map((field) => ({
|
|
3158
|
+
fieldId: field.id,
|
|
3159
|
+
title: field.title,
|
|
3160
|
+
type: field.type,
|
|
3161
|
+
rawValue: answers[field.id],
|
|
3162
|
+
displayValue: displaySubmittedValue(field, answers[field.id], translate),
|
|
3163
|
+
visible: visibility[field.id] === true,
|
|
3164
|
+
...field.metadata === void 0 ? {} : { metadata: field.metadata }
|
|
3165
|
+
}));
|
|
3166
|
+
}
|
|
3087
3167
|
function parseDraft(serialized) {
|
|
3088
3168
|
try {
|
|
3089
3169
|
const value = JSON.parse(serialized);
|
|
@@ -3102,15 +3182,65 @@ function parseDraft(serialized) {
|
|
|
3102
3182
|
return null;
|
|
3103
3183
|
}
|
|
3104
3184
|
}
|
|
3185
|
+
var DEFAULT_RENDERER_MESSAGES = {
|
|
3186
|
+
en: {
|
|
3187
|
+
submitButton: "Submit",
|
|
3188
|
+
submittingButton: "Submitting...",
|
|
3189
|
+
retryButton: "Retry",
|
|
3190
|
+
requiredField: "This field is required.",
|
|
3191
|
+
alreadySubmittedTitle: "Already Submitted",
|
|
3192
|
+
alreadySubmittedMessage: "Already submitted.",
|
|
3193
|
+
serverErrorSummary: "Submission failed. Please check your answers and try again.",
|
|
3194
|
+
confirmSensitiveDataTitle: "Sensitive data may be included",
|
|
3195
|
+
confirmSensitiveDataMessage: "The following answers may contain personal information. Continue submitting?",
|
|
3196
|
+
confirmButton: "Proceed",
|
|
3197
|
+
cancelButton: "Cancel"
|
|
3198
|
+
},
|
|
3199
|
+
ja: {
|
|
3200
|
+
submitButton: "\u9001\u4FE1\u3059\u308B",
|
|
3201
|
+
submittingButton: "\u9001\u4FE1\u4E2D...",
|
|
3202
|
+
retryButton: "\u518D\u9001\u4FE1\u3059\u308B",
|
|
3203
|
+
requiredField: "\u3053\u306E\u9805\u76EE\u306F\u5FC5\u9808\u3067\u3059",
|
|
3204
|
+
alreadySubmittedTitle: "\u56DE\u7B54\u6E08\u307F\u3067\u3059",
|
|
3205
|
+
alreadySubmittedMessage: "\u3053\u306E\u30A2\u30F3\u30B1\u30FC\u30C8\u306B\u306F\u3059\u3067\u306B\u56DE\u7B54\u3057\u3066\u3044\u307E\u3059\u3002",
|
|
3206
|
+
serverErrorSummary: "\u9001\u4FE1\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u5185\u5BB9\u3092\u3054\u78BA\u8A8D\u306E\u4E0A\u3001\u518D\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",
|
|
3207
|
+
confirmSensitiveDataTitle: "\u500B\u4EBA\u60C5\u5831\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059",
|
|
3208
|
+
confirmSensitiveDataMessage: "\u4EE5\u4E0B\u306E\u9805\u76EE\u306B\u500B\u4EBA\u60C5\u5831\u3068\u307F\u3089\u308C\u308B\u8A18\u8FF0\u304C\u3042\u308A\u307E\u3059\u3002\u3053\u306E\u307E\u307E\u9001\u4FE1\u3057\u3066\u3082\u3088\u308D\u3057\u3044\u3067\u3059\u304B\uFF1F",
|
|
3209
|
+
confirmButton: "\u3053\u306E\u307E\u307E\u9001\u4FE1",
|
|
3210
|
+
cancelButton: "\u4FEE\u6B63\u3059\u308B"
|
|
3211
|
+
}
|
|
3212
|
+
};
|
|
3213
|
+
function createRendererAttemptId() {
|
|
3214
|
+
const randomUuid = globalThis.crypto?.randomUUID;
|
|
3215
|
+
if (typeof randomUuid === "function") return randomUuid.call(globalThis.crypto);
|
|
3216
|
+
return `attempt-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
3217
|
+
}
|
|
3218
|
+
function maskSensitiveValue(finding) {
|
|
3219
|
+
if (finding.maskedText !== void 0) return finding.maskedText;
|
|
3220
|
+
const value = finding.matchedText;
|
|
3221
|
+
if (value === void 0) return void 0;
|
|
3222
|
+
if (finding.type === "email") {
|
|
3223
|
+
const separator = value.indexOf("@");
|
|
3224
|
+
if (separator > 0) return `${value.slice(0, Math.min(2, separator))}***${value.slice(separator)}`;
|
|
3225
|
+
}
|
|
3226
|
+
if (finding.type === "phone" || finding.type === "postal_code") return "***";
|
|
3227
|
+
return value.length <= 2 ? "***" : `${value.slice(0, 2)}***`;
|
|
3228
|
+
}
|
|
3105
3229
|
function ContextFormRenderer({
|
|
3106
3230
|
components = {},
|
|
3107
3231
|
className = "",
|
|
3108
3232
|
successMessageKey,
|
|
3109
3233
|
errorMessageKey,
|
|
3234
|
+
attemptIdFactory,
|
|
3235
|
+
messages = {},
|
|
3236
|
+
messageResolver,
|
|
3110
3237
|
autoSaveKey,
|
|
3111
3238
|
beforeSubmit,
|
|
3112
3239
|
onDraftSave,
|
|
3113
3240
|
successRenderMode = "append",
|
|
3241
|
+
submissionConfirmationRenderMode = "inline",
|
|
3242
|
+
showHiddenFieldsInSummary = false,
|
|
3243
|
+
fieldsClassName,
|
|
3114
3244
|
hideFormOnSuccess = false,
|
|
3115
3245
|
submissionGuards = [],
|
|
3116
3246
|
receiptStore,
|
|
@@ -3129,9 +3259,12 @@ function ContextFormRenderer({
|
|
|
3129
3259
|
const [guardMessage, setGuardMessage] = useState4(null);
|
|
3130
3260
|
const [guardsPending, setGuardsPending] = useState4(false);
|
|
3131
3261
|
const [receipt, setReceipt] = useState4(null);
|
|
3262
|
+
const [completionData, setCompletionData] = useState4(null);
|
|
3132
3263
|
const [receiptLoaded, setReceiptLoaded] = useState4(receiptStore === void 0);
|
|
3133
3264
|
const rendererSubmissionInFlight = useRef2(false);
|
|
3265
|
+
const fallbackAttemptId = useRef2(null);
|
|
3134
3266
|
const completionRef = useRef2(null);
|
|
3267
|
+
const confirmationRef = useRef2(null);
|
|
3135
3268
|
const pages = form.schema.pages;
|
|
3136
3269
|
const visiblePageIndexes = useMemo4(
|
|
3137
3270
|
() => pages === void 0 ? [] : pages.flatMap((page, index) => form.pageVisibility[page.id] === true ? [index] : []),
|
|
@@ -3144,6 +3277,22 @@ function ContextFormRenderer({
|
|
|
3144
3277
|
const submitState = confirmation === null && !guardsPending ? form.submitStatus : "confirming";
|
|
3145
3278
|
const interactionLocked = submitState === "confirming" || submitState === "submitting";
|
|
3146
3279
|
const isReplaceMode = successRenderMode === "replace" || hideFormOnSuccess;
|
|
3280
|
+
const resolveMessage = useCallback3(
|
|
3281
|
+
(key, fallback) => {
|
|
3282
|
+
const defaultText = fallback ?? DEFAULT_RENDERER_MESSAGES[form.locale.toLowerCase().startsWith("ja") ? "ja" : "en"][key] ?? key;
|
|
3283
|
+
const configured = messages[key];
|
|
3284
|
+
return messageResolver?.(key, configured ?? defaultText) ?? configured ?? defaultText;
|
|
3285
|
+
},
|
|
3286
|
+
[form.locale, messageResolver, messages]
|
|
3287
|
+
);
|
|
3288
|
+
const fieldTranslate = useCallback3(
|
|
3289
|
+
(key, params) => key === "validation.required" && (messages.requiredField !== void 0 || messageResolver !== void 0) ? resolveMessage("requiredField") : form.translate(key, params),
|
|
3290
|
+
[form.translate, messageResolver, messages.requiredField, resolveMessage]
|
|
3291
|
+
);
|
|
3292
|
+
const focusSubmitButton = useCallback3(() => {
|
|
3293
|
+
const button = formRef.current?.querySelector(".fe-submit, button[type='submit'], button");
|
|
3294
|
+
button?.focus();
|
|
3295
|
+
}, []);
|
|
3147
3296
|
useEffect3(() => {
|
|
3148
3297
|
let active = true;
|
|
3149
3298
|
if (receiptStore === void 0) {
|
|
@@ -3179,6 +3328,7 @@ function ContextFormRenderer({
|
|
|
3179
3328
|
);
|
|
3180
3329
|
const control = fieldContainer?.querySelector("input, select, textarea");
|
|
3181
3330
|
if (control !== void 0 && control !== null) {
|
|
3331
|
+
control.scrollIntoView?.({ behavior: "smooth", block: "center" });
|
|
3182
3332
|
control.focus();
|
|
3183
3333
|
setFocusFieldId(null);
|
|
3184
3334
|
}
|
|
@@ -3187,6 +3337,38 @@ function ContextFormRenderer({
|
|
|
3187
3337
|
if (!isReplaceMode || form.submitStatus !== "success") return;
|
|
3188
3338
|
completionRef.current?.focus();
|
|
3189
3339
|
}, [form.submitStatus, isReplaceMode]);
|
|
3340
|
+
useEffect3(() => {
|
|
3341
|
+
if (confirmation === null) return;
|
|
3342
|
+
const confirmButton = confirmationRef.current?.querySelector("[data-fe-confirm], button");
|
|
3343
|
+
confirmButton?.focus();
|
|
3344
|
+
if (submissionConfirmationRenderMode !== "dialog") return;
|
|
3345
|
+
const onKeyDown = (event) => {
|
|
3346
|
+
if (event.key === "Escape") {
|
|
3347
|
+
event.preventDefault();
|
|
3348
|
+
setConfirmation(null);
|
|
3349
|
+
globalThis.setTimeout(focusSubmitButton, 0);
|
|
3350
|
+
return;
|
|
3351
|
+
}
|
|
3352
|
+
if (event.key !== "Tab") return;
|
|
3353
|
+
const focusable = [
|
|
3354
|
+
...confirmationRef.current?.querySelectorAll(
|
|
3355
|
+
"button, [href], input, select, textarea, [tabindex]:not([tabindex='-1'])"
|
|
3356
|
+
) ?? []
|
|
3357
|
+
].filter((element) => !element.hasAttribute("disabled"));
|
|
3358
|
+
if (focusable.length === 0) return;
|
|
3359
|
+
const first = focusable[0];
|
|
3360
|
+
const last = focusable[focusable.length - 1];
|
|
3361
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
3362
|
+
event.preventDefault();
|
|
3363
|
+
last?.focus();
|
|
3364
|
+
} else if (!event.shiftKey && document.activeElement === last) {
|
|
3365
|
+
event.preventDefault();
|
|
3366
|
+
first?.focus();
|
|
3367
|
+
}
|
|
3368
|
+
};
|
|
3369
|
+
globalThis.addEventListener("keydown", onKeyDown);
|
|
3370
|
+
return () => globalThis.removeEventListener("keydown", onKeyDown);
|
|
3371
|
+
}, [confirmation, focusSubmitButton, submissionConfirmationRenderMode]);
|
|
3190
3372
|
useEffect3(() => {
|
|
3191
3373
|
if (autoSaveKey === void 0 || typeof globalThis.localStorage === "undefined") return;
|
|
3192
3374
|
const loadIdentity = `${autoSaveKey}:${form.schema.id}:${form.schema.version}`;
|
|
@@ -3283,17 +3465,24 @@ function ContextFormRenderer({
|
|
|
3283
3465
|
rendererSubmissionInFlight.current = true;
|
|
3284
3466
|
try {
|
|
3285
3467
|
let submissionAttempt;
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3468
|
+
let attemptId = fallbackAttemptId.current;
|
|
3469
|
+
if (attemptStore !== void 0) {
|
|
3470
|
+
submissionAttempt = await attemptStore.getOrCreate(form.schema.id, form.schema.version, attemptIdFactory);
|
|
3471
|
+
attemptId = submissionAttempt.attemptId;
|
|
3472
|
+
} else if (attemptId === null) {
|
|
3473
|
+
attemptId = attemptIdFactory?.() ?? createRendererAttemptId();
|
|
3474
|
+
fallbackAttemptId.current = attemptId;
|
|
3475
|
+
}
|
|
3476
|
+
if (attemptId === null) throw new Error("Unable to create a submission attempt id.");
|
|
3477
|
+
const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3478
|
+
const submitContext = {
|
|
3479
|
+
attemptId,
|
|
3480
|
+
formId: form.schema.id,
|
|
3481
|
+
formVersion: form.schema.version,
|
|
3482
|
+
locale: form.locale,
|
|
3483
|
+
submittedAt
|
|
3484
|
+
};
|
|
3485
|
+
const result = await form.submit(beforeSubmit, submitContext);
|
|
3297
3486
|
if (result.status === "invalid") {
|
|
3298
3487
|
const invalidPageIndex = pages?.findIndex(
|
|
3299
3488
|
(page) => firstInvalidFieldId === void 0 ? false : page.questionIds.includes(firstInvalidFieldId)
|
|
@@ -3302,14 +3491,40 @@ function ContextFormRenderer({
|
|
|
3302
3491
|
focusFirstIssue(firstInvalidFieldId);
|
|
3303
3492
|
return result;
|
|
3304
3493
|
}
|
|
3494
|
+
if (result.status === "error") {
|
|
3495
|
+
if (result.error instanceof FormSubmissionError) {
|
|
3496
|
+
const fieldErrors = result.error.payload.fieldErrors ?? {};
|
|
3497
|
+
form.setServerErrors?.(fieldErrors);
|
|
3498
|
+
const firstServerFieldId = form.schema.fields.find((field) => Object.hasOwn(fieldErrors, field.id))?.id ?? Object.keys(fieldErrors)[0];
|
|
3499
|
+
if (firstServerFieldId !== void 0) {
|
|
3500
|
+
const invalidPageIndex = pages?.findIndex((page) => page.questionIds.includes(firstServerFieldId));
|
|
3501
|
+
if (invalidPageIndex !== void 0 && invalidPageIndex >= 0) setCurrentPageIndex(invalidPageIndex);
|
|
3502
|
+
focusFirstIssue(firstServerFieldId);
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
return result;
|
|
3506
|
+
}
|
|
3305
3507
|
if (result.status !== "success") return result;
|
|
3508
|
+
const submittedAnswers = { ...form.values };
|
|
3509
|
+
const submittedItems = buildSubmittedItems(
|
|
3510
|
+
form.schema,
|
|
3511
|
+
submittedAnswers,
|
|
3512
|
+
form.visibility,
|
|
3513
|
+
(key) => form.translate(key),
|
|
3514
|
+
showHiddenFieldsInSummary
|
|
3515
|
+
);
|
|
3516
|
+
setCompletionData({
|
|
3517
|
+
answers: submittedAnswers,
|
|
3518
|
+
submittedItems,
|
|
3519
|
+
...result.response === void 0 ? {} : { response: result.response }
|
|
3520
|
+
});
|
|
3306
3521
|
if (receiptStore !== void 0) {
|
|
3307
3522
|
const response = result.response;
|
|
3308
|
-
const submissionId = response?.submissionId ?? submissionAttempt?.attemptId;
|
|
3523
|
+
const submissionId = response?.submissionId ?? submissionAttempt?.attemptId ?? attemptId;
|
|
3309
3524
|
const storedReceipt = {
|
|
3310
3525
|
formId: form.schema.id,
|
|
3311
3526
|
formVersion: form.schema.version,
|
|
3312
|
-
submittedAt: response?.submittedAt ??
|
|
3527
|
+
submittedAt: response?.submittedAt ?? submittedAt,
|
|
3313
3528
|
...submissionId === void 0 ? {} : { submissionId }
|
|
3314
3529
|
};
|
|
3315
3530
|
try {
|
|
@@ -3328,6 +3543,7 @@ function ContextFormRenderer({
|
|
|
3328
3543
|
} catch {
|
|
3329
3544
|
}
|
|
3330
3545
|
}
|
|
3546
|
+
if (attemptStore === void 0) fallbackAttemptId.current = null;
|
|
3331
3547
|
if (autoSaveKey !== void 0 && typeof globalThis.localStorage !== "undefined") {
|
|
3332
3548
|
globalThis.localStorage.removeItem(autoSaveKey);
|
|
3333
3549
|
setDraftRestored(false);
|
|
@@ -3349,6 +3565,7 @@ function ContextFormRenderer({
|
|
|
3349
3565
|
};
|
|
3350
3566
|
const cancelSubmission = () => {
|
|
3351
3567
|
setConfirmation(null);
|
|
3568
|
+
globalThis.setTimeout(focusSubmitButton, 0);
|
|
3352
3569
|
};
|
|
3353
3570
|
const resetReceipt = async () => {
|
|
3354
3571
|
if (receiptStore === void 0) return;
|
|
@@ -3366,144 +3583,220 @@ function ContextFormRenderer({
|
|
|
3366
3583
|
disabled: interactionLocked || submitState === "success",
|
|
3367
3584
|
onSubmit: () => void submitValues()
|
|
3368
3585
|
};
|
|
3369
|
-
return slots.renderSubmitButton?.(submitButtonProps) ?? /* @__PURE__ */
|
|
3586
|
+
return slots.renderSubmitButton?.(submitButtonProps) ?? /* @__PURE__ */ jsxs2("button", { className: "fe-submit", type: "submit", disabled: submitButtonProps.disabled, children: [
|
|
3587
|
+
submitState === "submitting" ? /* @__PURE__ */ jsx3("span", { className: "fe-spinner", "aria-hidden": "true" }) : null,
|
|
3588
|
+
submitState === "submitting" ? resolveMessage("submittingButton") : resolveMessage("submitButton", form.translate(form.schema.submitLabelKey ?? "form.submit"))
|
|
3589
|
+
] });
|
|
3370
3590
|
};
|
|
3371
3591
|
const completionMessage = form.schema.completionMessage ?? (successMessageKey === void 0 ? "Submitted." : form.translate(successMessageKey));
|
|
3372
|
-
const
|
|
3592
|
+
const activeCompletionData = completionData ?? {
|
|
3593
|
+
answers: { ...form.values },
|
|
3594
|
+
submittedItems: buildSubmittedItems(
|
|
3595
|
+
form.schema,
|
|
3596
|
+
form.values,
|
|
3597
|
+
form.visibility,
|
|
3598
|
+
(key) => form.translate(key),
|
|
3599
|
+
showHiddenFieldsInSummary
|
|
3600
|
+
)
|
|
3601
|
+
};
|
|
3602
|
+
const completionProps = {
|
|
3603
|
+
message: completionMessage,
|
|
3604
|
+
schema: form.schema,
|
|
3605
|
+
answers: activeCompletionData.answers,
|
|
3606
|
+
submittedItems: activeCompletionData.submittedItems,
|
|
3607
|
+
...activeCompletionData.response === void 0 ? {} : { response: activeCompletionData.response },
|
|
3608
|
+
onReset: form.reset
|
|
3609
|
+
};
|
|
3610
|
+
const completionRegion = /* @__PURE__ */ jsxs2("div", { ref: completionRef, className: "fe-completion", role: "status", "aria-live": "polite", tabIndex: -1, children: [
|
|
3611
|
+
slots.renderCompletion?.(completionProps) ?? /* @__PURE__ */ jsx3("div", { children: completionMessage }),
|
|
3612
|
+
slots.renderSubmittedValues?.({ items: activeCompletionData.submittedItems, schema: form.schema })
|
|
3613
|
+
] });
|
|
3614
|
+
const confirmationContent = /* @__PURE__ */ jsx3(
|
|
3615
|
+
"div",
|
|
3616
|
+
{
|
|
3617
|
+
ref: confirmationRef,
|
|
3618
|
+
className: "fe-submission-confirmation",
|
|
3619
|
+
role: submissionConfirmationRenderMode === "dialog" ? void 0 : "dialog",
|
|
3620
|
+
children: slots.renderSubmissionConfirmation?.({
|
|
3621
|
+
findings: confirmation?.findings ?? [],
|
|
3622
|
+
message: confirmation?.message ?? resolveMessage("confirmSensitiveDataMessage", form.translate("form.confirmSensitiveData")),
|
|
3623
|
+
schema: form.schema,
|
|
3624
|
+
visibleValues,
|
|
3625
|
+
onConfirm: confirmSubmission,
|
|
3626
|
+
onCancel: cancelSubmission
|
|
3627
|
+
}) ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
3628
|
+
/* @__PURE__ */ jsx3("h2", { children: resolveMessage("confirmSensitiveDataTitle") }),
|
|
3629
|
+
/* @__PURE__ */ jsx3("p", { children: confirmation?.message ?? resolveMessage("confirmSensitiveDataMessage", form.translate("form.confirmSensitiveData")) }),
|
|
3630
|
+
(confirmation?.findings ?? []).length === 0 ? null : /* @__PURE__ */ jsx3("ul", { children: (confirmation?.findings ?? []).map((finding, index) => {
|
|
3631
|
+
const field = form.schema.fields.find((candidate) => candidate.id === finding.fieldId);
|
|
3632
|
+
const typeLabels = form.locale.toLowerCase().startsWith("ja") ? { email: "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9", phone: "\u96FB\u8A71\u756A\u53F7", url: "URL", postal_code: "\u90F5\u4FBF\u756A\u53F7" } : { email: "Email address", phone: "Phone number", url: "URL", postal_code: "Postal code" };
|
|
3633
|
+
const typeLabel = finding.typeLabel ?? typeLabels[finding.type] ?? finding.type;
|
|
3634
|
+
const value = maskSensitiveValue(finding);
|
|
3635
|
+
return /* @__PURE__ */ jsxs2("li", { children: [
|
|
3636
|
+
/* @__PURE__ */ jsx3("span", { children: finding.fieldTitle ?? field?.title ?? finding.fieldId }),
|
|
3637
|
+
" ",
|
|
3638
|
+
/* @__PURE__ */ jsx3("span", { className: "fe-sensitive-type", children: typeLabel }),
|
|
3639
|
+
value === void 0 ? null : /* @__PURE__ */ jsxs2("span", { className: "fe-sensitive-value", children: [
|
|
3640
|
+
" ",
|
|
3641
|
+
value
|
|
3642
|
+
] })
|
|
3643
|
+
] }, `${finding.fieldId}-${finding.type}-${finding.start ?? index}`);
|
|
3644
|
+
}) }),
|
|
3645
|
+
/* @__PURE__ */ jsx3("button", { type: "button", "data-fe-confirm": "true", onClick: confirmSubmission, children: resolveMessage("confirmButton", form.translate("form.confirmSubmission")) }),
|
|
3646
|
+
/* @__PURE__ */ jsx3("button", { type: "button", onClick: cancelSubmission, children: resolveMessage("cancelButton", form.translate("form.cancelSubmission")) })
|
|
3647
|
+
] })
|
|
3648
|
+
}
|
|
3649
|
+
);
|
|
3373
3650
|
if (!receiptLoaded) return null;
|
|
3374
3651
|
if (receipt !== null) {
|
|
3375
3652
|
return /* @__PURE__ */ jsx3("div", { className: `fe-form fe-already-submitted ${className}`.trim(), children: slots.renderAlreadySubmitted?.({
|
|
3376
3653
|
receipt,
|
|
3377
3654
|
...receiptStore === void 0 ? {} : { onReset: () => void resetReceipt() }
|
|
3378
3655
|
}) ?? /* @__PURE__ */ jsxs2("div", { role: "status", children: [
|
|
3379
|
-
|
|
3380
|
-
|
|
3656
|
+
/* @__PURE__ */ jsx3("h2", { children: resolveMessage("alreadySubmittedTitle") }),
|
|
3657
|
+
/* @__PURE__ */ jsx3("p", { children: resolveMessage("alreadySubmittedMessage", form.translate("form.alreadySubmitted")) }),
|
|
3658
|
+
receiptStore === void 0 ? null : /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => void resetReceipt(), children: resolveMessage("submitButton", form.translate("form.submitAnother")) })
|
|
3381
3659
|
] }) });
|
|
3382
3660
|
}
|
|
3383
3661
|
if (form.submitStatus === "success" && isReplaceMode) {
|
|
3384
3662
|
return /* @__PURE__ */ jsx3("div", { className: `fe-form ${className}`.trim(), children: completionRegion });
|
|
3385
3663
|
}
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3664
|
+
if (confirmation !== null && submissionConfirmationRenderMode === "replace") {
|
|
3665
|
+
return /* @__PURE__ */ jsx3("div", { className: `fe-form ${className}`.trim(), children: confirmationContent });
|
|
3666
|
+
}
|
|
3667
|
+
return /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
3668
|
+
/* @__PURE__ */ jsxs2(
|
|
3669
|
+
"form",
|
|
3670
|
+
{
|
|
3671
|
+
ref: formRef,
|
|
3672
|
+
className: `fe-form ${className}`.trim(),
|
|
3673
|
+
noValidate: true,
|
|
3674
|
+
onSubmit: handleSubmit,
|
|
3675
|
+
"aria-hidden": confirmation !== null && submissionConfirmationRenderMode === "dialog" ? true : void 0,
|
|
3676
|
+
children: [
|
|
3677
|
+
slots.renderHeader?.({
|
|
3678
|
+
title: form.schema.title,
|
|
3679
|
+
...form.schema.description === void 0 ? {} : { description: form.schema.description }
|
|
3680
|
+
}) ?? /* @__PURE__ */ jsxs2("header", { className: "fe-header", children: [
|
|
3681
|
+
/* @__PURE__ */ jsx3("h1", { children: form.schema.title }),
|
|
3682
|
+
form.schema.description === void 0 ? null : /* @__PURE__ */ jsx3("p", { children: form.schema.description }),
|
|
3683
|
+
pages === void 0 ? null : /* @__PURE__ */ jsxs2("div", { className: "fe-progress", children: [
|
|
3684
|
+
/* @__PURE__ */ jsx3(
|
|
3685
|
+
"div",
|
|
3686
|
+
{
|
|
3687
|
+
className: "form-progress-bar",
|
|
3688
|
+
role: "progressbar",
|
|
3689
|
+
"aria-valuemin": 1,
|
|
3690
|
+
"aria-valuemax": visiblePageIndexes.length,
|
|
3691
|
+
"aria-valuenow": activeVisibleIndex + 1,
|
|
3692
|
+
children: /* @__PURE__ */ jsx3(
|
|
3693
|
+
"div",
|
|
3694
|
+
{
|
|
3695
|
+
className: "form-progress-fill",
|
|
3696
|
+
style: { width: `${(activeVisibleIndex + 1) / visiblePageIndexes.length * 100}%` }
|
|
3697
|
+
}
|
|
3698
|
+
)
|
|
3699
|
+
}
|
|
3700
|
+
),
|
|
3701
|
+
/* @__PURE__ */ jsx3("span", { children: form.translate("form.step", { current: activeVisibleIndex + 1, total: visiblePageIndexes.length }) })
|
|
3702
|
+
] }),
|
|
3703
|
+
draftRestored ? /* @__PURE__ */ jsx3("span", { className: "form-draft-badge", children: form.translate("form.draftRestored") }) : null
|
|
3704
|
+
] }),
|
|
3705
|
+
activePage === void 0 ? null : slots.renderPageHeader?.({
|
|
3706
|
+
page: activePage,
|
|
3707
|
+
pageIndex: activeVisibleIndex,
|
|
3708
|
+
totalPages: visiblePageIndexes.length
|
|
3709
|
+
}) ?? /* @__PURE__ */ jsxs2("div", { className: "fe-page-header", children: [
|
|
3710
|
+
activePage.title === void 0 ? null : /* @__PURE__ */ jsx3("h2", { className: "fe-page-title", children: activePage.title }),
|
|
3711
|
+
activePage.description === void 0 ? null : /* @__PURE__ */ jsx3("p", { className: "fe-page-description", children: activePage.description })
|
|
3712
|
+
] }),
|
|
3713
|
+
(() => {
|
|
3714
|
+
const fieldChildren = form.schema.fields.filter((field) => form.visibility[field.id] === true && (fieldIds === void 0 || fieldIds.has(field.id))).map((field) => {
|
|
3715
|
+
const error = form.errors[field.id];
|
|
3716
|
+
const props = {
|
|
3717
|
+
field,
|
|
3718
|
+
value: form.values[field.id],
|
|
3719
|
+
error,
|
|
3720
|
+
setValue: (value) => form.setValue(field.id, value),
|
|
3721
|
+
translate: fieldTranslate,
|
|
3722
|
+
inputId: `${prefix}-${field.id}`,
|
|
3723
|
+
errorId: `${prefix}-${field.id}-error`,
|
|
3724
|
+
helpId: `${prefix}-${field.id}-help`,
|
|
3725
|
+
...slots.renderCharacterCount === void 0 ? {} : { renderCharacterCount: slots.renderCharacterCount }
|
|
3726
|
+
};
|
|
3727
|
+
if (slots.renderField !== void 0) {
|
|
3728
|
+
return /* @__PURE__ */ jsx3(Fragment2, { children: slots.renderField({
|
|
3729
|
+
question: field,
|
|
3730
|
+
value: form.values[field.id],
|
|
3731
|
+
onChange: (value) => {
|
|
3732
|
+
if (isFormValue(value)) form.setValue(field.id, value);
|
|
3733
|
+
},
|
|
3734
|
+
...error === void 0 ? {} : { error }
|
|
3735
|
+
}) }, field.id);
|
|
3407
3736
|
}
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3737
|
+
const Component = components[field.type];
|
|
3738
|
+
return Component === void 0 ? /* @__PURE__ */ jsx3(DefaultField, { ...props }, field.id) : /* @__PURE__ */ jsx3(Component, { ...props }, field.id);
|
|
3739
|
+
});
|
|
3740
|
+
const fieldClassName = `fe-fields${fieldsClassName === void 0 ? "" : ` ${fieldsClassName}`}`;
|
|
3741
|
+
return slots.renderFields?.({ children: fieldChildren, className: fieldClassName }) ?? /* @__PURE__ */ jsx3("div", { className: fieldClassName, children: fieldChildren });
|
|
3742
|
+
})(),
|
|
3743
|
+
guardMessage === null ? null : /* @__PURE__ */ jsx3("div", { role: "alert", children: guardMessage }),
|
|
3744
|
+
confirmation !== null && submissionConfirmationRenderMode === "inline" ? confirmationContent : null,
|
|
3745
|
+
validationIssues.length === 0 ? null : slots.renderValidationSummary?.({ issues: validationIssues }) ?? /* @__PURE__ */ jsxs2("div", { className: "fe-validation-summary", role: "alert", children: [
|
|
3746
|
+
validationIssues.length,
|
|
3747
|
+
" validation error",
|
|
3748
|
+
validationIssues.length === 1 ? "" : "s",
|
|
3749
|
+
"."
|
|
3750
|
+
] }),
|
|
3751
|
+
pages === void 0 ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
3752
|
+
slots.renderNavigation?.({
|
|
3753
|
+
currentPage: 0,
|
|
3754
|
+
totalPages: 1,
|
|
3755
|
+
canPrev: false,
|
|
3756
|
+
canNext: false,
|
|
3757
|
+
onPrev: () => void 0,
|
|
3758
|
+
onNext: () => void 0
|
|
3759
|
+
}),
|
|
3760
|
+
renderSubmitButton()
|
|
3761
|
+
] }) : /* @__PURE__ */ jsxs2("div", { className: "form-step-navigation", children: [
|
|
3762
|
+
slots.renderNavigation?.({
|
|
3763
|
+
currentPage: activeVisibleIndex,
|
|
3764
|
+
totalPages: visiblePageIndexes.length,
|
|
3765
|
+
canPrev,
|
|
3766
|
+
canNext,
|
|
3767
|
+
onPrev: () => {
|
|
3768
|
+
if (!interactionLocked) setCurrentPageIndex(visiblePageIndexes[activeVisibleIndex - 1] ?? 0);
|
|
3769
|
+
},
|
|
3770
|
+
onNext: handleNext
|
|
3771
|
+
}) ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
3772
|
+
canPrev ? /* @__PURE__ */ jsx3(
|
|
3773
|
+
"button",
|
|
3774
|
+
{
|
|
3775
|
+
className: "btn-prev",
|
|
3776
|
+
type: "button",
|
|
3777
|
+
disabled: interactionLocked,
|
|
3778
|
+
onClick: () => setCurrentPageIndex(visiblePageIndexes[activeVisibleIndex - 1] ?? 0),
|
|
3779
|
+
children: form.translate("form.back")
|
|
3780
|
+
}
|
|
3781
|
+
) : null,
|
|
3782
|
+
canNext ? /* @__PURE__ */ jsx3("button", { className: "btn-next", type: "button", disabled: interactionLocked, onClick: handleNext, children: form.translate("form.next") }) : null
|
|
3783
|
+
] }),
|
|
3784
|
+
canNext ? null : renderSubmitButton()
|
|
3785
|
+
] }),
|
|
3786
|
+
/* @__PURE__ */ jsxs2("div", { className: "fe-status", "aria-live": "polite", children: [
|
|
3787
|
+
form.submitStatus === "success" ? completionRegion : null,
|
|
3788
|
+
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__ */ jsxs2("div", { role: "alert", children: [
|
|
3789
|
+
form.submitError.payload.formError,
|
|
3790
|
+
/* @__PURE__ */ jsx3("button", { type: "button", onClick: () => void submitValues(), children: resolveMessage("retryButton") })
|
|
3791
|
+
] }) : /* @__PURE__ */ jsxs2("div", { role: "alert", children: [
|
|
3792
|
+
errorMessageKey === void 0 ? resolveMessage("serverErrorSummary") : form.translate(errorMessageKey),
|
|
3793
|
+
/* @__PURE__ */ jsx3("button", { type: "button", onClick: () => void submitValues(), children: resolveMessage("retryButton") })
|
|
3794
|
+
] })) : null
|
|
3795
|
+
] })
|
|
3796
|
+
]
|
|
3445
3797
|
}
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
}) }),
|
|
3449
|
-
guardMessage === null ? null : /* @__PURE__ */ jsx3("div", { role: "alert", children: guardMessage }),
|
|
3450
|
-
confirmation === null ? null : slots.renderSubmissionConfirmation?.({
|
|
3451
|
-
findings: confirmation.findings,
|
|
3452
|
-
message: confirmation.message ?? form.translate("form.confirmSensitiveData"),
|
|
3453
|
-
schema: form.schema,
|
|
3454
|
-
visibleValues,
|
|
3455
|
-
onConfirm: confirmSubmission,
|
|
3456
|
-
onCancel: cancelSubmission
|
|
3457
|
-
}) ?? /* @__PURE__ */ jsxs2("div", { className: "fe-submission-confirmation", role: "dialog", "aria-modal": "true", children: [
|
|
3458
|
-
/* @__PURE__ */ jsx3("p", { children: confirmation.message ?? form.translate("form.confirmSensitiveData") }),
|
|
3459
|
-
/* @__PURE__ */ jsx3("button", { type: "button", onClick: confirmSubmission, children: form.translate("form.confirmSubmission") }),
|
|
3460
|
-
/* @__PURE__ */ jsx3("button", { type: "button", onClick: cancelSubmission, children: form.translate("form.cancelSubmission") })
|
|
3461
|
-
] }),
|
|
3462
|
-
validationIssues.length === 0 ? null : slots.renderValidationSummary?.({ issues: validationIssues }) ?? /* @__PURE__ */ jsxs2("div", { className: "fe-validation-summary", role: "alert", children: [
|
|
3463
|
-
validationIssues.length,
|
|
3464
|
-
" validation error",
|
|
3465
|
-
validationIssues.length === 1 ? "" : "s",
|
|
3466
|
-
"."
|
|
3467
|
-
] }),
|
|
3468
|
-
pages === void 0 ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
3469
|
-
slots.renderNavigation?.({
|
|
3470
|
-
currentPage: 0,
|
|
3471
|
-
totalPages: 1,
|
|
3472
|
-
canPrev: false,
|
|
3473
|
-
canNext: false,
|
|
3474
|
-
onPrev: () => void 0,
|
|
3475
|
-
onNext: () => void 0
|
|
3476
|
-
}),
|
|
3477
|
-
renderSubmitButton()
|
|
3478
|
-
] }) : /* @__PURE__ */ jsxs2("div", { className: "form-step-navigation", children: [
|
|
3479
|
-
slots.renderNavigation?.({
|
|
3480
|
-
currentPage: activeVisibleIndex,
|
|
3481
|
-
totalPages: visiblePageIndexes.length,
|
|
3482
|
-
canPrev,
|
|
3483
|
-
canNext,
|
|
3484
|
-
onPrev: () => {
|
|
3485
|
-
if (!interactionLocked) setCurrentPageIndex(visiblePageIndexes[activeVisibleIndex - 1] ?? 0);
|
|
3486
|
-
},
|
|
3487
|
-
onNext: handleNext
|
|
3488
|
-
}) ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
3489
|
-
canPrev ? /* @__PURE__ */ jsx3(
|
|
3490
|
-
"button",
|
|
3491
|
-
{
|
|
3492
|
-
className: "btn-prev",
|
|
3493
|
-
type: "button",
|
|
3494
|
-
disabled: interactionLocked,
|
|
3495
|
-
onClick: () => setCurrentPageIndex(visiblePageIndexes[activeVisibleIndex - 1] ?? 0),
|
|
3496
|
-
children: form.translate("form.back")
|
|
3497
|
-
}
|
|
3498
|
-
) : null,
|
|
3499
|
-
canNext ? /* @__PURE__ */ jsx3("button", { className: "btn-next", type: "button", disabled: interactionLocked, onClick: handleNext, children: form.translate("form.next") }) : null
|
|
3500
|
-
] }),
|
|
3501
|
-
canNext ? null : renderSubmitButton()
|
|
3502
|
-
] }),
|
|
3503
|
-
/* @__PURE__ */ jsxs2("div", { className: "fe-status", "aria-live": "polite", children: [
|
|
3504
|
-
form.submitStatus === "success" ? completionRegion : null,
|
|
3505
|
-
form.submitStatus === "error" && form.submitError !== null ? slots.renderSubmitError?.({ error: form.submitError, onRetry: () => void submitValues() }) ?? (errorMessageKey === void 0 ? null : /* @__PURE__ */ jsx3("div", { role: "alert", children: form.translate(errorMessageKey) })) : null
|
|
3506
|
-
] })
|
|
3798
|
+
),
|
|
3799
|
+
confirmation !== null && submissionConfirmationRenderMode === "dialog" ? /* @__PURE__ */ jsx3("div", { className: "fe-confirmation-dialog-backdrop", role: "dialog", "aria-modal": "true", children: confirmationContent }) : null
|
|
3507
3800
|
] });
|
|
3508
3801
|
}
|
|
3509
3802
|
var RENDERER_MESSAGES = {
|
|
@@ -3514,15 +3807,34 @@ var RENDERER_MESSAGES = {
|
|
|
3514
3807
|
"form.draftRestored": "Draft restored",
|
|
3515
3808
|
"form.submissionBlocked": "Submission blocked because sensitive data was detected.",
|
|
3516
3809
|
"form.confirmSensitiveData": "Sensitive data may be included. Confirm before submitting.",
|
|
3517
|
-
"form.confirmSubmission": "
|
|
3810
|
+
"form.confirmSubmission": "Proceed",
|
|
3518
3811
|
"form.cancelSubmission": "Cancel",
|
|
3812
|
+
"form.yes": "Yes",
|
|
3813
|
+
"form.no": "No",
|
|
3519
3814
|
"form.alreadySubmitted": "Already submitted.",
|
|
3520
3815
|
"form.submitAnother": "Submit another response",
|
|
3521
3816
|
"validation.required": "This field is required."
|
|
3522
3817
|
};
|
|
3818
|
+
var RENDERER_MESSAGES_JA = {
|
|
3819
|
+
"form.submit": "\u9001\u4FE1\u3059\u308B",
|
|
3820
|
+
"form.back": "\u623B\u308B",
|
|
3821
|
+
"form.next": "\u6B21\u3078",
|
|
3822
|
+
"form.step": "{{current}} / {{total}}",
|
|
3823
|
+
"form.draftRestored": "\u4E0B\u66F8\u304D\u3092\u5FA9\u5143\u3057\u307E\u3057\u305F",
|
|
3824
|
+
"form.submissionBlocked": "\u500B\u4EBA\u60C5\u5831\u304C\u691C\u51FA\u3055\u308C\u305F\u305F\u3081\u9001\u4FE1\u3067\u304D\u307E\u305B\u3093\u3002",
|
|
3825
|
+
"form.confirmSensitiveData": "\u500B\u4EBA\u60C5\u5831\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u9001\u4FE1\u524D\u306B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
3826
|
+
"form.confirmSubmission": "\u3053\u306E\u307E\u307E\u9001\u4FE1",
|
|
3827
|
+
"form.cancelSubmission": "\u4FEE\u6B63\u3059\u308B",
|
|
3828
|
+
"form.yes": "\u306F\u3044",
|
|
3829
|
+
"form.no": "\u3044\u3044\u3048",
|
|
3830
|
+
"form.alreadySubmitted": "\u56DE\u7B54\u6E08\u307F\u3067\u3059",
|
|
3831
|
+
"form.submitAnother": "\u5225\u306E\u56DE\u7B54\u3092\u9001\u4FE1",
|
|
3832
|
+
"validation.required": "\u3053\u306E\u9805\u76EE\u306F\u5FC5\u9808\u3067\u3059"
|
|
3833
|
+
};
|
|
3523
3834
|
var defaultRendererTranslator = {
|
|
3524
|
-
translate(key,
|
|
3525
|
-
|
|
3835
|
+
translate(key, locale, params = {}) {
|
|
3836
|
+
const localizedMessages = locale.toLowerCase().startsWith("ja") ? RENDERER_MESSAGES_JA : RENDERER_MESSAGES;
|
|
3837
|
+
return (localizedMessages[key] ?? key).replace(
|
|
3526
3838
|
/\{\{(\w+)\}\}/g,
|
|
3527
3839
|
(token, name) => Object.hasOwn(params, name) ? String(params[name]) : token
|
|
3528
3840
|
);
|
|
@@ -3556,6 +3868,7 @@ export {
|
|
|
3556
3868
|
FormBuilder,
|
|
3557
3869
|
FormProvider,
|
|
3558
3870
|
FormRenderer,
|
|
3871
|
+
FormSubmissionError,
|
|
3559
3872
|
createLocalStorageSubmissionAttemptStore,
|
|
3560
3873
|
createLocalStorageSubmissionReceiptStore,
|
|
3561
3874
|
resolveInitialFieldType,
|