@form-engine-ts/react 2.9.3 → 2.9.5
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 +17 -5
- package/dist/index.cjs +521 -363
- package/dist/index.d.cts +45 -8
- package/dist/index.d.ts +45 -8
- package/dist/index.js +522 -364
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -101,7 +101,7 @@ function createLocalStorageSubmissionAttemptStore(options = {}) {
|
|
|
101
101
|
import {
|
|
102
102
|
populateSchemaTranslations
|
|
103
103
|
} from "@form-engine-ts/core";
|
|
104
|
-
import { createContext, useContext, useState } from "react";
|
|
104
|
+
import { Children, createContext, isValidElement, useContext, useState } from "react";
|
|
105
105
|
|
|
106
106
|
// src/hooks/useFormBuilder.ts
|
|
107
107
|
import {
|
|
@@ -1058,7 +1058,7 @@ function BuilderButton(props) {
|
|
|
1058
1058
|
...props,
|
|
1059
1059
|
className: primitiveClassName(props.className, "feb-button", context.unstyled),
|
|
1060
1060
|
disabled: context.readOnly || props.disabled === true,
|
|
1061
|
-
readOnly: context.readOnly
|
|
1061
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1062
1062
|
}
|
|
1063
1063
|
);
|
|
1064
1064
|
}
|
|
@@ -1073,7 +1073,7 @@ function BuilderIconButton(props) {
|
|
|
1073
1073
|
icon,
|
|
1074
1074
|
className: primitiveClassName(props.className, "feb-icon-button", context.unstyled),
|
|
1075
1075
|
disabled: context.readOnly || props.disabled === true,
|
|
1076
|
-
readOnly: context.readOnly
|
|
1076
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1077
1077
|
}
|
|
1078
1078
|
);
|
|
1079
1079
|
}
|
|
@@ -1086,7 +1086,7 @@ function BuilderTextInput(props) {
|
|
|
1086
1086
|
...props,
|
|
1087
1087
|
className: primitiveClassName(props.className, "feb-input", context.unstyled),
|
|
1088
1088
|
disabled: context.readOnly || props.disabled === true,
|
|
1089
|
-
readOnly: context.readOnly
|
|
1089
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1090
1090
|
}
|
|
1091
1091
|
);
|
|
1092
1092
|
}
|
|
@@ -1099,7 +1099,7 @@ function BuilderTextArea(props) {
|
|
|
1099
1099
|
...props,
|
|
1100
1100
|
className: primitiveClassName(props.className, "feb-textarea", context.unstyled),
|
|
1101
1101
|
disabled: context.readOnly || props.disabled === true,
|
|
1102
|
-
readOnly: context.readOnly
|
|
1102
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1103
1103
|
}
|
|
1104
1104
|
);
|
|
1105
1105
|
}
|
|
@@ -1112,7 +1112,7 @@ function BuilderSelect(props) {
|
|
|
1112
1112
|
...props,
|
|
1113
1113
|
className: primitiveClassName(props.className, "feb-select", context.unstyled),
|
|
1114
1114
|
disabled: context.readOnly || props.disabled === true,
|
|
1115
|
-
readOnly: context.readOnly
|
|
1115
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1116
1116
|
}
|
|
1117
1117
|
);
|
|
1118
1118
|
}
|
|
@@ -1125,7 +1125,7 @@ function BuilderCheckbox(props) {
|
|
|
1125
1125
|
...props,
|
|
1126
1126
|
className: primitiveClassName(props.className, "feb-checkbox", context.unstyled),
|
|
1127
1127
|
disabled: context.readOnly || props.disabled === true,
|
|
1128
|
-
readOnly: context.readOnly
|
|
1128
|
+
readOnly: context.readOnly || props.readOnly === true
|
|
1129
1129
|
}
|
|
1130
1130
|
);
|
|
1131
1131
|
}
|
|
@@ -1169,6 +1169,7 @@ var BUILDER_DEFAULTS = {
|
|
|
1169
1169
|
"builder.basicSettings": "Basic settings",
|
|
1170
1170
|
"builder.formTitle": "Form title",
|
|
1171
1171
|
"builder.formDescription": "Form description",
|
|
1172
|
+
"builder.description": "Description",
|
|
1172
1173
|
"builder.moveUp": "Move {{title}} up",
|
|
1173
1174
|
"builder.moveDown": "Move {{title}} down",
|
|
1174
1175
|
"builder.delete": "Delete {{title}}",
|
|
@@ -1203,12 +1204,31 @@ var BUILDER_DEFAULTS = {
|
|
|
1203
1204
|
"builder.pageQuestion": "Question to move to the new page",
|
|
1204
1205
|
"builder.questionPage": "Page",
|
|
1205
1206
|
"builder.pageCondition": "Page display condition",
|
|
1207
|
+
"builder.unassigned": "Unassigned",
|
|
1206
1208
|
"builder.localization": "Localization",
|
|
1207
1209
|
"builder.defaultLocale": "Default locale",
|
|
1208
1210
|
"builder.supportedLocales": "Supported locales",
|
|
1209
1211
|
"builder.addLocale": "Add locale",
|
|
1210
1212
|
"builder.editLocale": "Edit locale",
|
|
1211
1213
|
"builder.autoTranslate": "Translate all text",
|
|
1214
|
+
"builder.translating": "Translating\u2026",
|
|
1215
|
+
"builder.translationLocale": "Translation locale",
|
|
1216
|
+
"builder.selectLocale": "Select a locale to edit translations.",
|
|
1217
|
+
"builder.translation": "{{locale}} translation",
|
|
1218
|
+
"builder.translatedFormTitle": "Translated form title",
|
|
1219
|
+
"builder.translatedFormDescription": "Translated form description",
|
|
1220
|
+
"builder.translatedCompletionMessage": "Translated completion message",
|
|
1221
|
+
"builder.translatedQuestionTitle": "Translated question title",
|
|
1222
|
+
"builder.translatedDescription": "Translated description",
|
|
1223
|
+
"builder.actions.moveUp": "Move up",
|
|
1224
|
+
"builder.actions.moveDown": "Move down",
|
|
1225
|
+
"builder.actions.delete": "Delete",
|
|
1226
|
+
"builder.actions.add": "Add",
|
|
1227
|
+
"builder.actions.edit": "Edit",
|
|
1228
|
+
"builder.actions.settings": "Settings",
|
|
1229
|
+
"builder.actions.translate": "Translate",
|
|
1230
|
+
"builder.actions.close": "Close",
|
|
1231
|
+
"builder.actions.dragHandle": "Reorder",
|
|
1212
1232
|
"builder.translationUnavailable": "Provide an async translation adapter to enable automatic translation.",
|
|
1213
1233
|
"builder.fieldType.text": "Text",
|
|
1214
1234
|
"builder.fieldType.textarea": "Textarea",
|
|
@@ -1229,12 +1249,81 @@ function interpolate(template, params) {
|
|
|
1229
1249
|
(token, name) => Object.hasOwn(params, name) ? String(params[name]) : token
|
|
1230
1250
|
);
|
|
1231
1251
|
}
|
|
1252
|
+
function BuilderSectionGroup({ children }) {
|
|
1253
|
+
return children;
|
|
1254
|
+
}
|
|
1255
|
+
function sectionGroupName(node) {
|
|
1256
|
+
if (!isValidElement(node) || node.type !== BuilderSectionGroup) return void 0;
|
|
1257
|
+
return node.props.name;
|
|
1258
|
+
}
|
|
1259
|
+
function OrderedBuilderSections({
|
|
1260
|
+
order,
|
|
1261
|
+
children
|
|
1262
|
+
}) {
|
|
1263
|
+
if (order === void 0) return children;
|
|
1264
|
+
const ranks = new Map(order.map((name, index) => [name, index]));
|
|
1265
|
+
const groups = Children.toArray(children);
|
|
1266
|
+
return groups.map((group, index) => ({ group, index, rank: ranks.get(sectionGroupName(group) ?? "questions") ?? order.length })).sort((left, right) => left.rank - right.rank || left.index - right.index).map(({ group }) => group);
|
|
1267
|
+
}
|
|
1232
1268
|
function fieldTypeKey(type) {
|
|
1233
1269
|
return `builder.fieldType.${type}`;
|
|
1234
1270
|
}
|
|
1235
1271
|
function operatorKey(operator) {
|
|
1236
1272
|
return `builder.operator.${operator}`;
|
|
1237
1273
|
}
|
|
1274
|
+
function manualTranslationContext(schema, locale, target, property, translatedText) {
|
|
1275
|
+
if (target.kind === "form") {
|
|
1276
|
+
if (property !== "title" && property !== "description" && property !== "completionMessage") return void 0;
|
|
1277
|
+
return {
|
|
1278
|
+
locale,
|
|
1279
|
+
kind: "form",
|
|
1280
|
+
nodeId: schema.id,
|
|
1281
|
+
property,
|
|
1282
|
+
sourceText: schema[property] ?? "",
|
|
1283
|
+
translatedText,
|
|
1284
|
+
...schema.translationMetadata?.[locale]?.[property] === void 0 ? {} : { existingTranslationMetadata: schema.translationMetadata[locale]?.[property] }
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
if (target.id === void 0) return void 0;
|
|
1288
|
+
if (target.kind === "field") {
|
|
1289
|
+
const field = schema.fields.find((candidate) => candidate.id === target.id);
|
|
1290
|
+
if (field === void 0 || property !== "title" && property !== "description") return void 0;
|
|
1291
|
+
return {
|
|
1292
|
+
locale,
|
|
1293
|
+
kind: "field",
|
|
1294
|
+
nodeId: field.id,
|
|
1295
|
+
property,
|
|
1296
|
+
sourceText: field[property] ?? "",
|
|
1297
|
+
translatedText,
|
|
1298
|
+
...field.translationMetadata?.[locale]?.[property] === void 0 ? {} : { existingTranslationMetadata: field.translationMetadata[locale]?.[property] }
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
if (target.kind === "page") {
|
|
1302
|
+
const page = schema.pages?.find((candidate) => candidate.id === target.id);
|
|
1303
|
+
if (page === void 0 || property !== "title" && property !== "description") return void 0;
|
|
1304
|
+
return {
|
|
1305
|
+
locale,
|
|
1306
|
+
kind: "page",
|
|
1307
|
+
nodeId: page.id,
|
|
1308
|
+
property,
|
|
1309
|
+
sourceText: page[property] ?? "",
|
|
1310
|
+
translatedText,
|
|
1311
|
+
...page.translationMetadata?.[locale]?.[property] === void 0 ? {} : { existingTranslationMetadata: page.translationMetadata[locale]?.[property] }
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
if (property !== "label") return void 0;
|
|
1315
|
+
const option = schema.fields.filter((field) => "options" in field).flatMap((field) => field.options).find((candidate) => candidate.id === target.id);
|
|
1316
|
+
if (option === void 0) return void 0;
|
|
1317
|
+
return {
|
|
1318
|
+
locale,
|
|
1319
|
+
kind: "option",
|
|
1320
|
+
nodeId: option.id,
|
|
1321
|
+
property,
|
|
1322
|
+
sourceText: option.label,
|
|
1323
|
+
translatedText,
|
|
1324
|
+
...option.translationMetadata?.[locale]?.[property] === void 0 ? {} : { existingTranslationMetadata: option.translationMetadata[locale]?.[property] }
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1238
1327
|
function defaultConditionValue(field) {
|
|
1239
1328
|
if (field.type === "checkbox") return true;
|
|
1240
1329
|
if (field.type === "number" || field.type === "rating") return field.min ?? 1;
|
|
@@ -1331,6 +1420,7 @@ function FormBuilder({
|
|
|
1331
1420
|
features,
|
|
1332
1421
|
components: componentOverrides,
|
|
1333
1422
|
slots,
|
|
1423
|
+
sectionOrder,
|
|
1334
1424
|
disableDefaultStyles = false,
|
|
1335
1425
|
unstyled = false
|
|
1336
1426
|
}) {
|
|
@@ -1348,6 +1438,7 @@ function FormBuilder({
|
|
|
1348
1438
|
const PagesSlot = slots?.pages;
|
|
1349
1439
|
const LocalizationSlot = slots?.localization;
|
|
1350
1440
|
const TranslationActionsSlot = slots?.translationActions;
|
|
1441
|
+
const resolvedSectionOrder = sectionOrder ?? slots?.sectionOrder;
|
|
1351
1442
|
const headless = useFormBuilder({
|
|
1352
1443
|
schema,
|
|
1353
1444
|
onChange,
|
|
@@ -1362,7 +1453,11 @@ function FormBuilder({
|
|
|
1362
1453
|
const [translationError, setTranslationError] = useState(null);
|
|
1363
1454
|
const [translationReport, setTranslationReport] = useState();
|
|
1364
1455
|
const translate = (key, params = {}) => {
|
|
1365
|
-
const
|
|
1456
|
+
const translatorParams = {};
|
|
1457
|
+
for (const [name, value] of Object.entries(params)) {
|
|
1458
|
+
if (typeof value === "string" || typeof value === "number") translatorParams[name] = value;
|
|
1459
|
+
}
|
|
1460
|
+
const translated = translator?.translate(key, locale, translatorParams);
|
|
1366
1461
|
return translated === void 0 ? interpolate(BUILDER_DEFAULTS[key] ?? key, params) : translated;
|
|
1367
1462
|
};
|
|
1368
1463
|
const pagesEnabled = features?.pages ?? true;
|
|
@@ -1487,25 +1582,30 @@ function FormBuilder({
|
|
|
1487
1582
|
setIsTranslating(false);
|
|
1488
1583
|
}
|
|
1489
1584
|
};
|
|
1490
|
-
const
|
|
1491
|
-
if (readOnly) return;
|
|
1492
|
-
const
|
|
1493
|
-
const
|
|
1494
|
-
|
|
1585
|
+
const setManualTranslation = (targetLocale, target, property, text) => {
|
|
1586
|
+
if (readOnly) return { success: true };
|
|
1587
|
+
const normalizedLocale = targetLocale.trim();
|
|
1588
|
+
const context = manualTranslationContext(schema, normalizedLocale, target, property, text);
|
|
1589
|
+
const metadata = context === void 0 ? void 0 : createManualTranslationMetadata?.(context);
|
|
1590
|
+
return executeAction(
|
|
1495
1591
|
() => headless.setLocaleTranslation(
|
|
1496
|
-
|
|
1592
|
+
normalizedLocale,
|
|
1497
1593
|
target,
|
|
1498
|
-
|
|
1499
|
-
|
|
1594
|
+
property,
|
|
1595
|
+
text,
|
|
1500
1596
|
metadata === void 0 ? void 0 : { metadata }
|
|
1501
1597
|
),
|
|
1502
1598
|
{
|
|
1503
|
-
action: "
|
|
1504
|
-
targetId:
|
|
1505
|
-
params: { locale:
|
|
1599
|
+
action: "setManualTranslation",
|
|
1600
|
+
...target.id === void 0 ? {} : { targetId: target.id },
|
|
1601
|
+
params: { locale: normalizedLocale, kind: target.kind, property }
|
|
1506
1602
|
}
|
|
1507
1603
|
);
|
|
1508
1604
|
};
|
|
1605
|
+
const updateManualTranslation = (context) => {
|
|
1606
|
+
const target = context.kind === "form" ? { kind: "form" } : { kind: context.kind, id: context.nodeId };
|
|
1607
|
+
setManualTranslation(context.locale, target, context.property, context.translatedText);
|
|
1608
|
+
};
|
|
1509
1609
|
const updateFormTranslation = (property, translatedText) => {
|
|
1510
1610
|
if (editingLocale.length === 0) return;
|
|
1511
1611
|
updateManualTranslation({
|
|
@@ -1614,6 +1714,7 @@ function FormBuilder({
|
|
|
1614
1714
|
...target.id === void 0 ? {} : { targetId: target.id },
|
|
1615
1715
|
params: { locale: targetLocale, property }
|
|
1616
1716
|
}),
|
|
1717
|
+
setManualTranslation,
|
|
1617
1718
|
addLocale: (targetLocale) => executeAction(() => headless.addLocale(targetLocale), {
|
|
1618
1719
|
action: "addLocale",
|
|
1619
1720
|
params: { locale: targetLocale }
|
|
@@ -1647,8 +1748,8 @@ function FormBuilder({
|
|
|
1647
1748
|
addOption(fieldId);
|
|
1648
1749
|
}
|
|
1649
1750
|
},
|
|
1650
|
-
children: /* @__PURE__ */
|
|
1651
|
-
/* @__PURE__ */ jsx(
|
|
1751
|
+
children: /* @__PURE__ */ jsx(Fieldset, { className: builderClass("form-engine-builder__controls"), disabled: readOnly, children: /* @__PURE__ */ jsxs(OrderedBuilderSections, { ...resolvedSectionOrder === void 0 ? {} : { order: resolvedSectionOrder }, children: [
|
|
1752
|
+
/* @__PURE__ */ jsx(BuilderSectionGroup, { name: "basicSettings", children: /* @__PURE__ */ jsx(
|
|
1652
1753
|
Section,
|
|
1653
1754
|
{
|
|
1654
1755
|
className: builderClass("form-engine-builder__basic-settings"),
|
|
@@ -1682,8 +1783,17 @@ function FormBuilder({
|
|
|
1682
1783
|
) })
|
|
1683
1784
|
] })
|
|
1684
1785
|
}
|
|
1685
|
-
),
|
|
1686
|
-
|
|
1786
|
+
) }),
|
|
1787
|
+
resolvedSectionOrder === void 0 ? null : /* @__PURE__ */ jsx(BuilderSectionGroup, { name: "completionMessage", children: /* @__PURE__ */ jsx(Section, { headingId: "builder-completion-message-heading", title: translate("builder.completionMessage"), children: /* @__PURE__ */ jsx(
|
|
1788
|
+
TextInput,
|
|
1789
|
+
{
|
|
1790
|
+
id: "builder-completion-message",
|
|
1791
|
+
label: translate("builder.completionMessage"),
|
|
1792
|
+
value: schema.completionMessage ?? "",
|
|
1793
|
+
onChange: (value) => setSourceText({ kind: "form" }, "completionMessage", value)
|
|
1794
|
+
}
|
|
1795
|
+
) }) }),
|
|
1796
|
+
/* @__PURE__ */ jsx(BuilderSectionGroup, { name: "questions", children: pagesEnabled ? PagesSlot === void 0 ? /* @__PURE__ */ jsx(
|
|
1687
1797
|
Section,
|
|
1688
1798
|
{
|
|
1689
1799
|
className: builderClass("form-engine-builder__pages"),
|
|
@@ -1733,6 +1843,7 @@ function FormBuilder({
|
|
|
1733
1843
|
ToolbarSlot,
|
|
1734
1844
|
{
|
|
1735
1845
|
schema,
|
|
1846
|
+
translate,
|
|
1736
1847
|
kind: "page",
|
|
1737
1848
|
targetId: page.id,
|
|
1738
1849
|
index: pageIndex,
|
|
@@ -1879,7 +1990,10 @@ function FormBuilder({
|
|
|
1879
1990
|
{
|
|
1880
1991
|
source,
|
|
1881
1992
|
condition: page.displayCondition,
|
|
1882
|
-
onChange: (condition) => updatePage(page.id, (current) => ({
|
|
1993
|
+
onChange: (condition) => updatePage(page.id, (current) => ({
|
|
1994
|
+
...current,
|
|
1995
|
+
displayCondition: condition
|
|
1996
|
+
})),
|
|
1883
1997
|
translate,
|
|
1884
1998
|
components
|
|
1885
1999
|
}
|
|
@@ -1914,20 +2028,22 @@ function FormBuilder({
|
|
|
1914
2028
|
PagesSlot,
|
|
1915
2029
|
{
|
|
1916
2030
|
schema,
|
|
2031
|
+
translate,
|
|
1917
2032
|
currentLocale: editingLocale,
|
|
2033
|
+
...features === void 0 ? {} : { features },
|
|
1918
2034
|
readOnly,
|
|
1919
2035
|
actions,
|
|
1920
2036
|
components
|
|
1921
2037
|
}
|
|
1922
|
-
) : null,
|
|
1923
|
-
localizationEnabled ? LocalizationSlot === void 0 ? /* @__PURE__ */ jsxs(
|
|
2038
|
+
) : null }),
|
|
2039
|
+
/* @__PURE__ */ jsx(BuilderSectionGroup, { name: "localization", children: localizationEnabled ? LocalizationSlot === void 0 ? /* @__PURE__ */ jsxs(
|
|
1924
2040
|
Section,
|
|
1925
2041
|
{
|
|
1926
2042
|
className: builderClass("form-engine-builder__localization"),
|
|
1927
2043
|
headingId: "builder-localization-heading",
|
|
1928
2044
|
title: translate("builder.localization"),
|
|
1929
2045
|
children: [
|
|
1930
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2046
|
+
resolvedSectionOrder === void 0 ? /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
1931
2047
|
TextInput,
|
|
1932
2048
|
{
|
|
1933
2049
|
id: "builder-completion-message",
|
|
@@ -1935,7 +2051,7 @@ function FormBuilder({
|
|
|
1935
2051
|
value: schema.completionMessage ?? "",
|
|
1936
2052
|
onChange: (value) => setSourceText({ kind: "form" }, "completionMessage", value)
|
|
1937
2053
|
}
|
|
1938
|
-
) }),
|
|
2054
|
+
) }) : null,
|
|
1939
2055
|
/* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
1940
2056
|
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
1941
2057
|
TextInput,
|
|
@@ -2000,12 +2116,14 @@ function FormBuilder({
|
|
|
2000
2116
|
TranslationActionsSlot,
|
|
2001
2117
|
{
|
|
2002
2118
|
schema,
|
|
2119
|
+
translate,
|
|
2003
2120
|
currentLocale: editingLocale,
|
|
2004
2121
|
onAutoTranslate: () => void translateAll(),
|
|
2005
2122
|
isTranslating,
|
|
2006
2123
|
...translationError === null ? {} : { translationError },
|
|
2007
2124
|
...translationReport === void 0 ? {} : { translationReport },
|
|
2008
2125
|
onClearTranslationError: () => setTranslationError(null),
|
|
2126
|
+
translationAdapterAvailable: translationAdapter !== void 0,
|
|
2009
2127
|
readOnly,
|
|
2010
2128
|
actions,
|
|
2011
2129
|
components
|
|
@@ -2049,17 +2167,20 @@ function FormBuilder({
|
|
|
2049
2167
|
LocalizationSlot,
|
|
2050
2168
|
{
|
|
2051
2169
|
schema,
|
|
2170
|
+
translate,
|
|
2052
2171
|
currentLocale: editingLocale,
|
|
2053
2172
|
onCurrentLocaleChange: setEditingLocale,
|
|
2054
2173
|
onAutoTranslate: () => void translateAll(),
|
|
2055
2174
|
isTranslating,
|
|
2056
2175
|
...translationError === null ? {} : { translationError },
|
|
2176
|
+
...policy === void 0 ? {} : { policy },
|
|
2177
|
+
translationAdapterAvailable: translationAdapter !== void 0,
|
|
2057
2178
|
readOnly,
|
|
2058
2179
|
actions,
|
|
2059
2180
|
components
|
|
2060
2181
|
}
|
|
2061
|
-
) : null,
|
|
2062
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__list"), children: schema.fields.map((field, index) => {
|
|
2182
|
+
) : null }),
|
|
2183
|
+
/* @__PURE__ */ jsx(BuilderSectionGroup, { name: "questions", children: /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__list"), children: schema.fields.map((field, index) => {
|
|
2063
2184
|
const condition = field.displayCondition;
|
|
2064
2185
|
const source = condition === void 0 ? void 0 : schema.fields.find((item) => item.id === condition.questionId);
|
|
2065
2186
|
const availableSources = schema.fields.slice(0, index);
|
|
@@ -2071,7 +2192,9 @@ function FormBuilder({
|
|
|
2071
2192
|
field,
|
|
2072
2193
|
index,
|
|
2073
2194
|
currentLocale: editingLocale,
|
|
2195
|
+
translate,
|
|
2074
2196
|
...policy === void 0 ? {} : { policy },
|
|
2197
|
+
...features === void 0 ? {} : { features },
|
|
2075
2198
|
readOnly,
|
|
2076
2199
|
actions,
|
|
2077
2200
|
components
|
|
@@ -2079,348 +2202,362 @@ function FormBuilder({
|
|
|
2079
2202
|
field.id
|
|
2080
2203
|
);
|
|
2081
2204
|
}
|
|
2082
|
-
return /* @__PURE__ */ jsxs(
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
total: schema.fields.length,
|
|
2120
|
-
title: field.title,
|
|
2121
|
-
onMoveUp: () => moveField(index, -1),
|
|
2122
|
-
onMoveDown: () => moveField(index, 1),
|
|
2123
|
-
onRemove: () => removeField(field.id),
|
|
2124
|
-
readOnly,
|
|
2125
|
-
actions,
|
|
2126
|
-
components
|
|
2127
|
-
}
|
|
2128
|
-
) }),
|
|
2129
|
-
/* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2130
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2131
|
-
TextInput,
|
|
2132
|
-
{
|
|
2133
|
-
id: `builder-field-${field.id}-title`,
|
|
2134
|
-
name: `fields.${field.id}.title`,
|
|
2135
|
-
label: translate("builder.questionTitle"),
|
|
2136
|
-
required: true,
|
|
2137
|
-
error: field.title.trim().length === 0,
|
|
2138
|
-
helperText: field.title.trim().length === 0 ? translate("builder.required") : "",
|
|
2139
|
-
"aria-describedby": field.title.trim().length === 0 ? `builder-field-${field.id}-title-error` : void 0,
|
|
2140
|
-
value: field.title,
|
|
2141
|
-
placeholder: translate("builder.questionTitlePlaceholder"),
|
|
2142
|
-
onChange: (value) => updateField(field.id, (current) => ({
|
|
2143
|
-
...current,
|
|
2144
|
-
title: value.trim().length === 0 ? current.title : value
|
|
2145
|
-
}))
|
|
2146
|
-
}
|
|
2147
|
-
) }),
|
|
2148
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2149
|
-
Select,
|
|
2150
|
-
{
|
|
2151
|
-
id: `builder-field-${field.id}-type`,
|
|
2152
|
-
label: translate("builder.type"),
|
|
2153
|
-
value: field.type,
|
|
2154
|
-
onChange: (value) => changeType(field.id, value),
|
|
2155
|
-
options: FIELD_TYPES.filter(
|
|
2156
|
-
(type) => policy?.allowedFieldTypes === void 0 || policy.allowedFieldTypes.includes(type)
|
|
2157
|
-
).map((type) => ({ value: type, label: translate(fieldTypeKey(type)) }))
|
|
2158
|
-
}
|
|
2159
|
-
) }),
|
|
2160
|
-
/* @__PURE__ */ jsx(
|
|
2161
|
-
Checkbox,
|
|
2162
|
-
{
|
|
2163
|
-
className: builderClass("form-engine-builder__check"),
|
|
2164
|
-
checked: field.required === true,
|
|
2165
|
-
onChange: (checked) => updateField(field.id, (current) => ({ ...current, required: checked })),
|
|
2166
|
-
label: translate("builder.required")
|
|
2167
|
-
}
|
|
2168
|
-
)
|
|
2169
|
-
] }),
|
|
2170
|
-
!pagesEnabled || schema.pages === void 0 ? null : /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2171
|
-
Select,
|
|
2172
|
-
{
|
|
2173
|
-
id: `builder-field-${field.id}-page`,
|
|
2174
|
-
label: translate("builder.questionPage"),
|
|
2175
|
-
value: pageForField(field.id)?.id ?? "",
|
|
2176
|
-
onChange: (value) => assignFieldToPage(field.id, value),
|
|
2177
|
-
options: schema.pages.map((page, pageIndex) => ({
|
|
2178
|
-
value: page.id,
|
|
2179
|
-
label: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}`
|
|
2180
|
-
}))
|
|
2181
|
-
}
|
|
2182
|
-
) }),
|
|
2183
|
-
!localizationEnabled || editingLocale.length === 0 ? null : /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__translation-editor"), children: [
|
|
2184
|
-
/* @__PURE__ */ jsx("strong", { children: editingLocale }),
|
|
2185
|
-
/* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2186
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2187
|
-
TextInput,
|
|
2205
|
+
return /* @__PURE__ */ jsxs(
|
|
2206
|
+
Fieldset,
|
|
2207
|
+
{
|
|
2208
|
+
className: builderClass("form-engine-builder__question"),
|
|
2209
|
+
legend: field.title,
|
|
2210
|
+
children: [
|
|
2211
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__toolbar"), children: ToolbarSlot === void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2212
|
+
/* @__PURE__ */ jsx(
|
|
2213
|
+
IconButton,
|
|
2214
|
+
{
|
|
2215
|
+
actionType: "moveUp",
|
|
2216
|
+
title: translate("builder.moveUp", { title: field.title }),
|
|
2217
|
+
disabled: index === 0,
|
|
2218
|
+
onClick: () => moveField(index, -1)
|
|
2219
|
+
}
|
|
2220
|
+
),
|
|
2221
|
+
/* @__PURE__ */ jsx(
|
|
2222
|
+
IconButton,
|
|
2223
|
+
{
|
|
2224
|
+
actionType: "moveDown",
|
|
2225
|
+
title: translate("builder.moveDown", { title: field.title }),
|
|
2226
|
+
disabled: index === schema.fields.length - 1,
|
|
2227
|
+
onClick: () => moveField(index, 1)
|
|
2228
|
+
}
|
|
2229
|
+
),
|
|
2230
|
+
/* @__PURE__ */ jsx(
|
|
2231
|
+
IconButton,
|
|
2232
|
+
{
|
|
2233
|
+
actionType: "delete",
|
|
2234
|
+
disabled: schema.fields.length === 1,
|
|
2235
|
+
onClick: () => removeField(field.id),
|
|
2236
|
+
"aria-label": translate("builder.delete", { title: field.title }),
|
|
2237
|
+
title: translate("builder.delete", { title: field.title })
|
|
2238
|
+
}
|
|
2239
|
+
)
|
|
2240
|
+
] }) : /* @__PURE__ */ jsx(
|
|
2241
|
+
ToolbarSlot,
|
|
2188
2242
|
{
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
})
|
|
2243
|
+
schema,
|
|
2244
|
+
translate,
|
|
2245
|
+
kind: "field",
|
|
2246
|
+
targetId: field.id,
|
|
2247
|
+
index,
|
|
2248
|
+
total: schema.fields.length,
|
|
2249
|
+
title: field.title,
|
|
2250
|
+
onMoveUp: () => moveField(index, -1),
|
|
2251
|
+
onMoveDown: () => moveField(index, 1),
|
|
2252
|
+
onRemove: () => removeField(field.id),
|
|
2253
|
+
readOnly,
|
|
2254
|
+
actions,
|
|
2255
|
+
components
|
|
2203
2256
|
}
|
|
2204
2257
|
) }),
|
|
2205
|
-
/* @__PURE__ */
|
|
2206
|
-
|
|
2258
|
+
/* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2259
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2260
|
+
TextInput,
|
|
2261
|
+
{
|
|
2262
|
+
id: `builder-field-${field.id}-title`,
|
|
2263
|
+
name: `fields.${field.id}.title`,
|
|
2264
|
+
label: translate("builder.questionTitle"),
|
|
2265
|
+
required: true,
|
|
2266
|
+
error: field.title.trim().length === 0,
|
|
2267
|
+
helperText: field.title.trim().length === 0 ? translate("builder.required") : "",
|
|
2268
|
+
"aria-describedby": field.title.trim().length === 0 ? `builder-field-${field.id}-title-error` : void 0,
|
|
2269
|
+
value: field.title,
|
|
2270
|
+
placeholder: translate("builder.questionTitlePlaceholder"),
|
|
2271
|
+
onChange: (value) => updateField(field.id, (current) => ({
|
|
2272
|
+
...current,
|
|
2273
|
+
title: value.trim().length === 0 ? current.title : value
|
|
2274
|
+
}))
|
|
2275
|
+
}
|
|
2276
|
+
) }),
|
|
2277
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2278
|
+
Select,
|
|
2279
|
+
{
|
|
2280
|
+
id: `builder-field-${field.id}-type`,
|
|
2281
|
+
label: translate("builder.type"),
|
|
2282
|
+
value: field.type,
|
|
2283
|
+
onChange: (value) => changeType(field.id, value),
|
|
2284
|
+
options: FIELD_TYPES.filter(
|
|
2285
|
+
(type) => policy?.allowedFieldTypes === void 0 || policy.allowedFieldTypes.includes(type)
|
|
2286
|
+
).map((type) => ({ value: type, label: translate(fieldTypeKey(type)) }))
|
|
2287
|
+
}
|
|
2288
|
+
) }),
|
|
2289
|
+
/* @__PURE__ */ jsx(
|
|
2290
|
+
Checkbox,
|
|
2291
|
+
{
|
|
2292
|
+
className: builderClass("form-engine-builder__check"),
|
|
2293
|
+
checked: field.required === true,
|
|
2294
|
+
onChange: (checked) => updateField(field.id, (current) => ({ ...current, required: checked })),
|
|
2295
|
+
label: translate("builder.required")
|
|
2296
|
+
}
|
|
2297
|
+
)
|
|
2298
|
+
] }),
|
|
2299
|
+
!pagesEnabled || schema.pages === void 0 ? null : /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2300
|
+
Select,
|
|
2207
2301
|
{
|
|
2208
|
-
id: `builder-field-${field.id}
|
|
2209
|
-
label: translate("builder.
|
|
2210
|
-
value: field.
|
|
2211
|
-
onChange: (value) =>
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
sourceText: field.description ?? "",
|
|
2217
|
-
translatedText: value,
|
|
2218
|
-
...field.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
|
|
2219
|
-
existingTranslationMetadata: field.translationMetadata[editingLocale]?.description
|
|
2220
|
-
}
|
|
2221
|
-
})
|
|
2302
|
+
id: `builder-field-${field.id}-page`,
|
|
2303
|
+
label: translate("builder.questionPage"),
|
|
2304
|
+
value: pageForField(field.id)?.id ?? "",
|
|
2305
|
+
onChange: (value) => assignFieldToPage(field.id, value),
|
|
2306
|
+
options: schema.pages.map((page, pageIndex) => ({
|
|
2307
|
+
value: page.id,
|
|
2308
|
+
label: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}`
|
|
2309
|
+
}))
|
|
2222
2310
|
}
|
|
2223
|
-
) })
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2311
|
+
) }),
|
|
2312
|
+
!localizationEnabled || editingLocale.length === 0 ? null : /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__translation-editor"), children: [
|
|
2313
|
+
/* @__PURE__ */ jsx("strong", { children: editingLocale }),
|
|
2314
|
+
/* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2315
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2316
|
+
TextInput,
|
|
2317
|
+
{
|
|
2318
|
+
id: `builder-field-${field.id}-${editingLocale}-title`,
|
|
2319
|
+
label: translate("builder.questionTitle"),
|
|
2320
|
+
value: field.translations?.[editingLocale]?.title ?? "",
|
|
2321
|
+
onChange: (value) => updateManualTranslation({
|
|
2322
|
+
locale: editingLocale,
|
|
2323
|
+
kind: "field",
|
|
2324
|
+
nodeId: field.id,
|
|
2325
|
+
property: "title",
|
|
2326
|
+
sourceText: field.title,
|
|
2327
|
+
translatedText: value,
|
|
2328
|
+
...field.translationMetadata?.[editingLocale]?.title === void 0 ? {} : {
|
|
2329
|
+
existingTranslationMetadata: field.translationMetadata[editingLocale]?.title
|
|
2330
|
+
}
|
|
2331
|
+
})
|
|
2332
|
+
}
|
|
2333
|
+
) }),
|
|
2334
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2335
|
+
TextInput,
|
|
2336
|
+
{
|
|
2337
|
+
id: `builder-field-${field.id}-${editingLocale}-description`,
|
|
2338
|
+
label: translate("builder.pageDescription"),
|
|
2339
|
+
value: field.translations?.[editingLocale]?.description ?? "",
|
|
2340
|
+
onChange: (value) => updateManualTranslation({
|
|
2341
|
+
locale: editingLocale,
|
|
2342
|
+
kind: "field",
|
|
2343
|
+
nodeId: field.id,
|
|
2344
|
+
property: "description",
|
|
2345
|
+
sourceText: field.description ?? "",
|
|
2346
|
+
translatedText: value,
|
|
2347
|
+
...field.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
|
|
2348
|
+
existingTranslationMetadata: field.translationMetadata[editingLocale]?.description
|
|
2349
|
+
}
|
|
2350
|
+
})
|
|
2351
|
+
}
|
|
2352
|
+
) })
|
|
2353
|
+
] }),
|
|
2354
|
+
"options" in field ? field.options.map((option, optionIndex) => /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2355
|
+
TextInput,
|
|
2356
|
+
{
|
|
2357
|
+
id: `builder-option-${option.id}-${editingLocale}`,
|
|
2358
|
+
label: `${translate("builder.optionLabel", { index: optionIndex + 1 })} (${editingLocale})`,
|
|
2359
|
+
value: option.translations?.[editingLocale] ?? "",
|
|
2360
|
+
onChange: (value) => updateManualTranslation({
|
|
2361
|
+
locale: editingLocale,
|
|
2362
|
+
kind: "option",
|
|
2363
|
+
nodeId: option.id,
|
|
2364
|
+
property: "label",
|
|
2365
|
+
sourceText: option.label,
|
|
2366
|
+
translatedText: value,
|
|
2367
|
+
...option.translationMetadata?.[editingLocale]?.label === void 0 ? {} : {
|
|
2368
|
+
existingTranslationMetadata: option.translationMetadata[editingLocale]?.label
|
|
2369
|
+
}
|
|
2370
|
+
})
|
|
2240
2371
|
}
|
|
2241
|
-
})
|
|
2242
|
-
}
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
field.type === "rating" ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2246
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2247
|
-
TextInput,
|
|
2248
|
-
{
|
|
2249
|
-
id: `builder-field-${field.id}-minimum`,
|
|
2250
|
-
label: translate("builder.minimum"),
|
|
2251
|
-
type: "number",
|
|
2252
|
-
value: String(field.min ?? 1),
|
|
2253
|
-
onChange: (value) => {
|
|
2254
|
-
const min = Number(value);
|
|
2255
|
-
if (!Number.isInteger(min)) return;
|
|
2256
|
-
updateField(
|
|
2257
|
-
field.id,
|
|
2258
|
-
(current) => current.type === "rating" ? { ...current, min, max: Math.max(min, current.max ?? 5) } : current
|
|
2259
|
-
);
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
) }),
|
|
2263
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2264
|
-
TextInput,
|
|
2265
|
-
{
|
|
2266
|
-
id: `builder-field-${field.id}-maximum`,
|
|
2267
|
-
label: translate("builder.maximum"),
|
|
2268
|
-
type: "number",
|
|
2269
|
-
value: String(field.max ?? 5),
|
|
2270
|
-
onChange: (value) => {
|
|
2271
|
-
const max = Number(value);
|
|
2272
|
-
if (!Number.isInteger(max)) return;
|
|
2273
|
-
updateField(
|
|
2274
|
-
field.id,
|
|
2275
|
-
(current) => current.type === "rating" ? { ...current, min: Math.min(current.min ?? 1, max), max } : current
|
|
2276
|
-
);
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
) })
|
|
2280
|
-
] }) : null,
|
|
2281
|
-
"options" in field ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__options"), children: [
|
|
2282
|
-
/* @__PURE__ */ jsx("strong", { children: translate("builder.options") }),
|
|
2283
|
-
field.options.map(
|
|
2284
|
-
(option, optionIndex) => OptionEditorSlot === void 0 ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__option"), children: [
|
|
2285
|
-
/* @__PURE__ */ jsx(
|
|
2372
|
+
) }, option.id)) : null
|
|
2373
|
+
] }),
|
|
2374
|
+
field.type === "rating" ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2375
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2286
2376
|
TextInput,
|
|
2287
2377
|
{
|
|
2288
|
-
id: `builder-
|
|
2289
|
-
label: translate("builder.
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
onChange: (value) =>
|
|
2378
|
+
id: `builder-field-${field.id}-minimum`,
|
|
2379
|
+
label: translate("builder.minimum"),
|
|
2380
|
+
type: "number",
|
|
2381
|
+
value: String(field.min ?? 1),
|
|
2382
|
+
onChange: (value) => {
|
|
2383
|
+
const min = Number(value);
|
|
2384
|
+
if (!Number.isInteger(min)) return;
|
|
2385
|
+
updateField(
|
|
2386
|
+
field.id,
|
|
2387
|
+
(current) => current.type === "rating" ? { ...current, min, max: Math.max(min, current.max ?? 5) } : current
|
|
2388
|
+
);
|
|
2389
|
+
}
|
|
2293
2390
|
}
|
|
2294
|
-
),
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
{
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2391
|
+
) }),
|
|
2392
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2393
|
+
TextInput,
|
|
2394
|
+
{
|
|
2395
|
+
id: `builder-field-${field.id}-maximum`,
|
|
2396
|
+
label: translate("builder.maximum"),
|
|
2397
|
+
type: "number",
|
|
2398
|
+
value: String(field.max ?? 5),
|
|
2399
|
+
onChange: (value) => {
|
|
2400
|
+
const max = Number(value);
|
|
2401
|
+
if (!Number.isInteger(max)) return;
|
|
2402
|
+
updateField(
|
|
2403
|
+
field.id,
|
|
2404
|
+
(current) => current.type === "rating" ? { ...current, min: Math.min(current.min ?? 1, max), max } : current
|
|
2405
|
+
);
|
|
2303
2406
|
}
|
|
2304
|
-
|
|
2407
|
+
}
|
|
2408
|
+
) })
|
|
2409
|
+
] }) : null,
|
|
2410
|
+
"options" in field ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__options"), children: [
|
|
2411
|
+
/* @__PURE__ */ jsx("strong", { children: translate("builder.options") }),
|
|
2412
|
+
field.options.map(
|
|
2413
|
+
(option, optionIndex) => OptionEditorSlot === void 0 ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__option"), children: [
|
|
2414
|
+
/* @__PURE__ */ jsx(
|
|
2415
|
+
TextInput,
|
|
2416
|
+
{
|
|
2417
|
+
id: `builder-option-${option.id}`,
|
|
2418
|
+
label: translate("builder.optionLabel", { index: optionIndex + 1 }),
|
|
2419
|
+
value: option.label,
|
|
2420
|
+
placeholder: translate("builder.optionLabelPlaceholder"),
|
|
2421
|
+
onChange: (value) => value.trim().length === 0 ? void 0 : updateOption(field.id, option.id, value)
|
|
2422
|
+
}
|
|
2423
|
+
),
|
|
2424
|
+
ToolbarSlot === void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2425
|
+
/* @__PURE__ */ jsx(
|
|
2426
|
+
IconButton,
|
|
2427
|
+
{
|
|
2428
|
+
actionType: "moveUp",
|
|
2429
|
+
title: translate("builder.moveUp", { title: option.label }),
|
|
2430
|
+
disabled: optionIndex === 0,
|
|
2431
|
+
onClick: () => moveOption(field.id, option.id, optionIndex - 1)
|
|
2432
|
+
}
|
|
2433
|
+
),
|
|
2434
|
+
/* @__PURE__ */ jsx(
|
|
2435
|
+
IconButton,
|
|
2436
|
+
{
|
|
2437
|
+
actionType: "moveDown",
|
|
2438
|
+
title: translate("builder.moveDown", { title: option.label }),
|
|
2439
|
+
disabled: optionIndex === field.options.length - 1,
|
|
2440
|
+
onClick: () => moveOption(field.id, option.id, optionIndex + 1)
|
|
2441
|
+
}
|
|
2442
|
+
),
|
|
2443
|
+
/* @__PURE__ */ jsx(
|
|
2444
|
+
IconButton,
|
|
2445
|
+
{
|
|
2446
|
+
actionType: "delete",
|
|
2447
|
+
disabled: field.options.length === 1,
|
|
2448
|
+
onClick: () => removeOption(field.id, option.id),
|
|
2449
|
+
title: translate("builder.remove")
|
|
2450
|
+
}
|
|
2451
|
+
)
|
|
2452
|
+
] }) : /* @__PURE__ */ jsx(
|
|
2453
|
+
ToolbarSlot,
|
|
2454
|
+
{
|
|
2455
|
+
schema,
|
|
2456
|
+
translate,
|
|
2457
|
+
kind: "option",
|
|
2458
|
+
targetId: option.id,
|
|
2459
|
+
index: optionIndex,
|
|
2460
|
+
total: field.options.length,
|
|
2461
|
+
title: option.label,
|
|
2462
|
+
onMoveUp: () => moveOption(field.id, option.id, optionIndex - 1),
|
|
2463
|
+
onMoveDown: () => moveOption(field.id, option.id, optionIndex + 1),
|
|
2464
|
+
onRemove: () => removeOption(field.id, option.id),
|
|
2465
|
+
readOnly,
|
|
2466
|
+
actions,
|
|
2467
|
+
components
|
|
2468
|
+
}
|
|
2469
|
+
)
|
|
2470
|
+
] }, option.id) : /* @__PURE__ */ jsx(
|
|
2471
|
+
OptionEditorSlot,
|
|
2472
|
+
{
|
|
2473
|
+
schema,
|
|
2474
|
+
field,
|
|
2475
|
+
option,
|
|
2476
|
+
index: optionIndex,
|
|
2477
|
+
currentLocale: editingLocale,
|
|
2478
|
+
translate,
|
|
2479
|
+
readOnly,
|
|
2480
|
+
actions,
|
|
2481
|
+
components
|
|
2482
|
+
},
|
|
2483
|
+
option.id
|
|
2484
|
+
)
|
|
2485
|
+
),
|
|
2486
|
+
/* @__PURE__ */ jsx(
|
|
2487
|
+
Button,
|
|
2488
|
+
{
|
|
2489
|
+
action: "addOption",
|
|
2490
|
+
targetId: field.id,
|
|
2491
|
+
disabled: policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
|
|
2492
|
+
onClick: () => addOption(field.id),
|
|
2493
|
+
children: translate("builder.addOption")
|
|
2494
|
+
}
|
|
2495
|
+
)
|
|
2496
|
+
] }) : null,
|
|
2497
|
+
conditionsEnabled ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__condition"), children: [
|
|
2498
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2499
|
+
Select,
|
|
2500
|
+
{
|
|
2501
|
+
id: `builder-field-${field.id}-condition`,
|
|
2502
|
+
label: translate("builder.displayCondition"),
|
|
2503
|
+
value: condition?.questionId ?? "",
|
|
2504
|
+
onChange: (value) => {
|
|
2505
|
+
const selected = schema.fields.find((item) => item.id === value);
|
|
2506
|
+
setDisplayCondition(
|
|
2507
|
+
field.id,
|
|
2508
|
+
selected === void 0 ? void 0 : conditionWithValue(
|
|
2509
|
+
selected.id,
|
|
2510
|
+
conditionOperators(selected)[0] ?? "not_empty",
|
|
2511
|
+
defaultConditionValue(selected)
|
|
2512
|
+
)
|
|
2513
|
+
);
|
|
2514
|
+
},
|
|
2515
|
+
options: [
|
|
2516
|
+
{ value: "", label: translate("builder.alwaysVisible") },
|
|
2517
|
+
...availableSources.map((candidate) => ({
|
|
2518
|
+
value: candidate.id,
|
|
2519
|
+
label: candidate.title
|
|
2520
|
+
}))
|
|
2521
|
+
]
|
|
2522
|
+
}
|
|
2523
|
+
) }),
|
|
2524
|
+
condition !== void 0 && source !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2305
2525
|
/* @__PURE__ */ jsx(
|
|
2306
|
-
|
|
2526
|
+
Select,
|
|
2307
2527
|
{
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2528
|
+
"aria-label": translate("builder.conditionOperator"),
|
|
2529
|
+
value: condition.operator,
|
|
2530
|
+
onChange: (value) => {
|
|
2531
|
+
const operator = value;
|
|
2532
|
+
setDisplayCondition(
|
|
2533
|
+
field.id,
|
|
2534
|
+
conditionWithValue(source.id, operator, defaultConditionValue(source))
|
|
2535
|
+
);
|
|
2536
|
+
},
|
|
2537
|
+
options: conditionOperators(source).map((operator) => ({
|
|
2538
|
+
value: operator,
|
|
2539
|
+
label: translate(operatorKey(operator))
|
|
2540
|
+
}))
|
|
2312
2541
|
}
|
|
2313
2542
|
),
|
|
2314
2543
|
/* @__PURE__ */ jsx(
|
|
2315
|
-
|
|
2544
|
+
ConditionValueEditor,
|
|
2316
2545
|
{
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2546
|
+
source,
|
|
2547
|
+
condition,
|
|
2548
|
+
onChange: (next) => setDisplayCondition(field.id, next),
|
|
2549
|
+
translate,
|
|
2550
|
+
components
|
|
2321
2551
|
}
|
|
2322
2552
|
)
|
|
2323
|
-
] }) :
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
title: option.label,
|
|
2332
|
-
onMoveUp: () => moveOption(field.id, option.id, optionIndex - 1),
|
|
2333
|
-
onMoveDown: () => moveOption(field.id, option.id, optionIndex + 1),
|
|
2334
|
-
onRemove: () => removeOption(field.id, option.id),
|
|
2335
|
-
readOnly,
|
|
2336
|
-
actions,
|
|
2337
|
-
components
|
|
2338
|
-
}
|
|
2339
|
-
)
|
|
2340
|
-
] }, option.id) : /* @__PURE__ */ jsx(
|
|
2341
|
-
OptionEditorSlot,
|
|
2342
|
-
{
|
|
2343
|
-
schema,
|
|
2344
|
-
field,
|
|
2345
|
-
option,
|
|
2346
|
-
index: optionIndex,
|
|
2347
|
-
currentLocale: editingLocale,
|
|
2348
|
-
readOnly,
|
|
2349
|
-
actions,
|
|
2350
|
-
components
|
|
2351
|
-
},
|
|
2352
|
-
option.id
|
|
2353
|
-
)
|
|
2354
|
-
),
|
|
2355
|
-
/* @__PURE__ */ jsx(
|
|
2356
|
-
Button,
|
|
2357
|
-
{
|
|
2358
|
-
action: "addOption",
|
|
2359
|
-
targetId: field.id,
|
|
2360
|
-
disabled: policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
|
|
2361
|
-
onClick: () => addOption(field.id),
|
|
2362
|
-
children: translate("builder.addOption")
|
|
2363
|
-
}
|
|
2364
|
-
)
|
|
2365
|
-
] }) : null,
|
|
2366
|
-
conditionsEnabled ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__condition"), children: [
|
|
2367
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2368
|
-
Select,
|
|
2369
|
-
{
|
|
2370
|
-
id: `builder-field-${field.id}-condition`,
|
|
2371
|
-
label: translate("builder.displayCondition"),
|
|
2372
|
-
value: condition?.questionId ?? "",
|
|
2373
|
-
onChange: (value) => {
|
|
2374
|
-
const selected = schema.fields.find((item) => item.id === value);
|
|
2375
|
-
setDisplayCondition(
|
|
2376
|
-
field.id,
|
|
2377
|
-
selected === void 0 ? void 0 : conditionWithValue(
|
|
2378
|
-
selected.id,
|
|
2379
|
-
conditionOperators(selected)[0] ?? "not_empty",
|
|
2380
|
-
defaultConditionValue(selected)
|
|
2381
|
-
)
|
|
2382
|
-
);
|
|
2383
|
-
},
|
|
2384
|
-
options: [
|
|
2385
|
-
{ value: "", label: translate("builder.alwaysVisible") },
|
|
2386
|
-
...availableSources.map((candidate) => ({ value: candidate.id, label: candidate.title }))
|
|
2387
|
-
]
|
|
2388
|
-
}
|
|
2389
|
-
) }),
|
|
2390
|
-
condition !== void 0 && source !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2391
|
-
/* @__PURE__ */ jsx(
|
|
2392
|
-
Select,
|
|
2393
|
-
{
|
|
2394
|
-
"aria-label": translate("builder.conditionOperator"),
|
|
2395
|
-
value: condition.operator,
|
|
2396
|
-
onChange: (value) => {
|
|
2397
|
-
const operator = value;
|
|
2398
|
-
setDisplayCondition(
|
|
2399
|
-
field.id,
|
|
2400
|
-
conditionWithValue(source.id, operator, defaultConditionValue(source))
|
|
2401
|
-
);
|
|
2402
|
-
},
|
|
2403
|
-
options: conditionOperators(source).map((operator) => ({
|
|
2404
|
-
value: operator,
|
|
2405
|
-
label: translate(operatorKey(operator))
|
|
2406
|
-
}))
|
|
2407
|
-
}
|
|
2408
|
-
),
|
|
2409
|
-
/* @__PURE__ */ jsx(
|
|
2410
|
-
ConditionValueEditor,
|
|
2411
|
-
{
|
|
2412
|
-
source,
|
|
2413
|
-
condition,
|
|
2414
|
-
onChange: (next) => setDisplayCondition(field.id, next),
|
|
2415
|
-
translate,
|
|
2416
|
-
components
|
|
2417
|
-
}
|
|
2418
|
-
)
|
|
2419
|
-
] }) : null
|
|
2420
|
-
] }) : null
|
|
2421
|
-
] }, field.id);
|
|
2422
|
-
}) }),
|
|
2423
|
-
/* @__PURE__ */ jsx(
|
|
2553
|
+
] }) : null
|
|
2554
|
+
] }) : null
|
|
2555
|
+
]
|
|
2556
|
+
},
|
|
2557
|
+
field.id
|
|
2558
|
+
);
|
|
2559
|
+
}) }) }),
|
|
2560
|
+
/* @__PURE__ */ jsx(BuilderSectionGroup, { name: "addQuestion", children: /* @__PURE__ */ jsx(
|
|
2424
2561
|
Button,
|
|
2425
2562
|
{
|
|
2426
2563
|
className: builderClass("form-engine-builder__add"),
|
|
@@ -2429,8 +2566,8 @@ function FormBuilder({
|
|
|
2429
2566
|
onClick: addField,
|
|
2430
2567
|
children: translate("builder.addQuestion")
|
|
2431
2568
|
}
|
|
2432
|
-
)
|
|
2433
|
-
] })
|
|
2569
|
+
) })
|
|
2570
|
+
] }) })
|
|
2434
2571
|
}
|
|
2435
2572
|
)
|
|
2436
2573
|
}
|
|
@@ -2973,6 +3110,8 @@ function ContextFormRenderer({
|
|
|
2973
3110
|
autoSaveKey,
|
|
2974
3111
|
beforeSubmit,
|
|
2975
3112
|
onDraftSave,
|
|
3113
|
+
successRenderMode = "append",
|
|
3114
|
+
hideFormOnSuccess = false,
|
|
2976
3115
|
submissionGuards = [],
|
|
2977
3116
|
receiptStore,
|
|
2978
3117
|
attemptStore,
|
|
@@ -2988,9 +3127,11 @@ function ContextFormRenderer({
|
|
|
2988
3127
|
const [focusFieldId, setFocusFieldId] = useState4(null);
|
|
2989
3128
|
const [confirmation, setConfirmation] = useState4(null);
|
|
2990
3129
|
const [guardMessage, setGuardMessage] = useState4(null);
|
|
3130
|
+
const [guardsPending, setGuardsPending] = useState4(false);
|
|
2991
3131
|
const [receipt, setReceipt] = useState4(null);
|
|
2992
3132
|
const [receiptLoaded, setReceiptLoaded] = useState4(receiptStore === void 0);
|
|
2993
3133
|
const rendererSubmissionInFlight = useRef2(false);
|
|
3134
|
+
const completionRef = useRef2(null);
|
|
2994
3135
|
const pages = form.schema.pages;
|
|
2995
3136
|
const visiblePageIndexes = useMemo4(
|
|
2996
3137
|
() => pages === void 0 ? [] : pages.flatMap((page, index) => form.pageVisibility[page.id] === true ? [index] : []),
|
|
@@ -3000,8 +3141,9 @@ function ContextFormRenderer({
|
|
|
3000
3141
|
const activeVisibleIndex = visiblePageIndexes.indexOf(currentPageIndex);
|
|
3001
3142
|
const fieldIds = activePage === void 0 ? void 0 : new Set(activePage.questionIds);
|
|
3002
3143
|
const visibleValues = useMemo4(() => selectVisibleAnswers2(form.schema, form.values), [form.schema, form.values]);
|
|
3003
|
-
const submitState = confirmation === null ? form.submitStatus : "confirming";
|
|
3144
|
+
const submitState = confirmation === null && !guardsPending ? form.submitStatus : "confirming";
|
|
3004
3145
|
const interactionLocked = submitState === "confirming" || submitState === "submitting";
|
|
3146
|
+
const isReplaceMode = successRenderMode === "replace" || hideFormOnSuccess;
|
|
3005
3147
|
useEffect3(() => {
|
|
3006
3148
|
let active = true;
|
|
3007
3149
|
if (receiptStore === void 0) {
|
|
@@ -3041,6 +3183,10 @@ function ContextFormRenderer({
|
|
|
3041
3183
|
setFocusFieldId(null);
|
|
3042
3184
|
}
|
|
3043
3185
|
}, [focusFieldId]);
|
|
3186
|
+
useEffect3(() => {
|
|
3187
|
+
if (!isReplaceMode || form.submitStatus !== "success") return;
|
|
3188
|
+
completionRef.current?.focus();
|
|
3189
|
+
}, [form.submitStatus, isReplaceMode]);
|
|
3044
3190
|
useEffect3(() => {
|
|
3045
3191
|
if (autoSaveKey === void 0 || typeof globalThis.localStorage === "undefined") return;
|
|
3046
3192
|
const loadIdentity = `${autoSaveKey}:${form.schema.id}:${form.schema.version}`;
|
|
@@ -3106,13 +3252,14 @@ function ContextFormRenderer({
|
|
|
3106
3252
|
};
|
|
3107
3253
|
};
|
|
3108
3254
|
const submitValues = async (guardsConfirmed = false) => {
|
|
3109
|
-
if (rendererSubmissionInFlight.current || confirmation !== null && !guardsConfirmed) {
|
|
3255
|
+
if (rendererSubmissionInFlight.current || submitState === "submitting" || submitState === "success" || confirmation !== null && !guardsConfirmed) {
|
|
3110
3256
|
return { status: "cancelled" };
|
|
3111
3257
|
}
|
|
3112
3258
|
const validation = validateAnswers2(form.schema, form.values);
|
|
3113
3259
|
const firstInvalidFieldId = validation.issues[0]?.fieldId;
|
|
3114
3260
|
if (validation.valid && !guardsConfirmed && submissionGuards.length > 0) {
|
|
3115
3261
|
rendererSubmissionInFlight.current = true;
|
|
3262
|
+
setGuardsPending(true);
|
|
3116
3263
|
try {
|
|
3117
3264
|
const guardResult = await runSubmissionGuards(submissionGuards);
|
|
3118
3265
|
if (guardResult.status === "block") {
|
|
@@ -3129,6 +3276,7 @@ function ContextFormRenderer({
|
|
|
3129
3276
|
}
|
|
3130
3277
|
} finally {
|
|
3131
3278
|
rendererSubmissionInFlight.current = false;
|
|
3279
|
+
setGuardsPending(false);
|
|
3132
3280
|
}
|
|
3133
3281
|
}
|
|
3134
3282
|
setGuardMessage(null);
|
|
@@ -3166,7 +3314,6 @@ function ContextFormRenderer({
|
|
|
3166
3314
|
};
|
|
3167
3315
|
try {
|
|
3168
3316
|
await receiptStore.save(storedReceipt);
|
|
3169
|
-
setReceipt(storedReceipt);
|
|
3170
3317
|
} catch (cause) {
|
|
3171
3318
|
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
3172
3319
|
try {
|
|
@@ -3193,7 +3340,7 @@ function ContextFormRenderer({
|
|
|
3193
3340
|
};
|
|
3194
3341
|
const handleSubmit = (event) => {
|
|
3195
3342
|
event.preventDefault();
|
|
3196
|
-
if (
|
|
3343
|
+
if (submitState === "submitting" || submitState === "confirming" || submitState === "success") return;
|
|
3197
3344
|
void submitValues();
|
|
3198
3345
|
};
|
|
3199
3346
|
const confirmSubmission = () => {
|
|
@@ -3212,7 +3359,17 @@ function ContextFormRenderer({
|
|
|
3212
3359
|
const validationIssues = Object.values(form.errors).filter((issue) => issue !== void 0);
|
|
3213
3360
|
const canPrev = pages !== void 0 && activeVisibleIndex > 0;
|
|
3214
3361
|
const canNext = pages !== void 0 && activeVisibleIndex < visiblePageIndexes.length - 1;
|
|
3215
|
-
const renderSubmitButton = () =>
|
|
3362
|
+
const renderSubmitButton = () => {
|
|
3363
|
+
const submitButtonProps = {
|
|
3364
|
+
isSubmitting: submitState === "submitting",
|
|
3365
|
+
submitStatus: submitState,
|
|
3366
|
+
disabled: interactionLocked || submitState === "success",
|
|
3367
|
+
onSubmit: () => void submitValues()
|
|
3368
|
+
};
|
|
3369
|
+
return slots.renderSubmitButton?.(submitButtonProps) ?? /* @__PURE__ */ jsx3("button", { className: "fe-submit", type: "submit", disabled: submitButtonProps.disabled, children: form.translate(form.schema.submitLabelKey ?? "form.submit") });
|
|
3370
|
+
};
|
|
3371
|
+
const completionMessage = form.schema.completionMessage ?? (successMessageKey === void 0 ? "Submitted." : form.translate(successMessageKey));
|
|
3372
|
+
const completionRegion = /* @__PURE__ */ jsx3("div", { ref: completionRef, className: "fe-completion", role: "status", "aria-live": "polite", tabIndex: -1, children: slots.renderCompletion?.({ message: completionMessage }) ?? /* @__PURE__ */ jsx3("div", { children: completionMessage }) });
|
|
3216
3373
|
if (!receiptLoaded) return null;
|
|
3217
3374
|
if (receipt !== null) {
|
|
3218
3375
|
return /* @__PURE__ */ jsx3("div", { className: `fe-form fe-already-submitted ${className}`.trim(), children: slots.renderAlreadySubmitted?.({
|
|
@@ -3223,6 +3380,9 @@ function ContextFormRenderer({
|
|
|
3223
3380
|
receiptStore === void 0 ? null : /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => void resetReceipt(), children: form.translate("form.submitAnother") })
|
|
3224
3381
|
] }) });
|
|
3225
3382
|
}
|
|
3383
|
+
if (form.submitStatus === "success" && isReplaceMode) {
|
|
3384
|
+
return /* @__PURE__ */ jsx3("div", { className: `fe-form ${className}`.trim(), children: completionRegion });
|
|
3385
|
+
}
|
|
3226
3386
|
return /* @__PURE__ */ jsxs2("form", { ref: formRef, className: `fe-form ${className}`.trim(), noValidate: true, onSubmit: handleSubmit, children: [
|
|
3227
3387
|
slots.renderHeader?.({
|
|
3228
3388
|
title: form.schema.title,
|
|
@@ -3341,9 +3501,7 @@ function ContextFormRenderer({
|
|
|
3341
3501
|
canNext ? null : renderSubmitButton()
|
|
3342
3502
|
] }),
|
|
3343
3503
|
/* @__PURE__ */ jsxs2("div", { className: "fe-status", "aria-live": "polite", children: [
|
|
3344
|
-
form.submitStatus === "success" ?
|
|
3345
|
-
message: form.schema.completionMessage ?? (successMessageKey === void 0 ? "Submitted." : form.translate(successMessageKey))
|
|
3346
|
-
}) ?? /* @__PURE__ */ jsx3("div", { role: "status", children: form.schema.completionMessage ?? (successMessageKey === void 0 ? "Submitted." : form.translate(successMessageKey)) }) : null,
|
|
3504
|
+
form.submitStatus === "success" ? completionRegion : null,
|
|
3347
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
|
|
3348
3506
|
] })
|
|
3349
3507
|
] });
|