@form-engine-ts/react 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/index.cjs +149 -16
- package/dist/index.d.cts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +147 -16
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -72,6 +72,11 @@ controls `pages`, `localization`, and `conditions` authoring surfaces; each defa
|
|
|
72
72
|
set, locale addition becomes a selector containing only unregistered allowed locales, and the action is disabled at
|
|
73
73
|
`maxLocales`.
|
|
74
74
|
|
|
75
|
+
`fieldEditorControls` makes the standard field editor's title, description, required flag, type selector, options,
|
|
76
|
+
display conditions, text limits, rating bounds, and number limits independently `editable`, `readOnly`, or `hidden`.
|
|
77
|
+
`fieldTypeOptions` can provide an explicit order, comparator, or transformation for generated type choices; the default
|
|
78
|
+
choices are copied before they are changed.
|
|
79
|
+
|
|
75
80
|
Visual Builder has two independent design-system extension layers. `components` replaces normalized primitives such as
|
|
76
81
|
`Button`, `TextInput`, `TextArea`, `Select`, `Checkbox`, `Section`, and `Fieldset`. `slots` replaces complete authoring
|
|
77
82
|
surfaces: `toolbar`, `fieldEditor`, `optionEditor`, `pages`, `localization`, or `translationActions`. Slot props expose
|
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,8 @@ __export(index_exports, {
|
|
|
29
29
|
createLocalStorageSubmissionAttemptStore: () => createLocalStorageSubmissionAttemptStore,
|
|
30
30
|
createLocalStorageSubmissionReceiptStore: () => createLocalStorageSubmissionReceiptStore,
|
|
31
31
|
isTranslationUnresolved: () => isTranslationUnresolved,
|
|
32
|
+
resolveFieldEditorControls: () => resolveFieldEditorControls,
|
|
33
|
+
resolveFieldTypeSelectOptions: () => resolveFieldTypeSelectOptions,
|
|
32
34
|
resolveInitialFieldType: () => resolveInitialFieldType,
|
|
33
35
|
resolveTranslation: () => resolveTranslation,
|
|
34
36
|
submissionReceiptQueryKey: () => submissionReceiptQueryKey,
|
|
@@ -1291,6 +1293,34 @@ var FIELD_TYPES = [
|
|
|
1291
1293
|
"checkbox",
|
|
1292
1294
|
"radio"
|
|
1293
1295
|
];
|
|
1296
|
+
var DEFAULT_FIELD_EDITOR_CONTROL_MODE = "editable";
|
|
1297
|
+
function resolveFieldEditorControls(config = {}) {
|
|
1298
|
+
return {
|
|
1299
|
+
title: config.title ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1300
|
+
description: config.description ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1301
|
+
required: config.required ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1302
|
+
typeSelect: config.typeSelect ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1303
|
+
options: config.options ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1304
|
+
displayConditions: config.displayConditions ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1305
|
+
textLimits: config.textLimits ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1306
|
+
ratingBounds: config.ratingBounds ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1307
|
+
numberLimits: config.numberLimits ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
function resolveFieldTypeSelectOptions(options, config, context) {
|
|
1311
|
+
let resolved = [...options];
|
|
1312
|
+
if (config?.transform !== void 0) resolved = [...config.transform(resolved, context)];
|
|
1313
|
+
if (config?.order !== void 0) {
|
|
1314
|
+
const ranks = new Map(config.order.map((type, index) => [type, index]));
|
|
1315
|
+
resolved.sort((left, right) => {
|
|
1316
|
+
const leftRank = ranks.get(left.value) ?? config.order?.length ?? 0;
|
|
1317
|
+
const rightRank = ranks.get(right.value) ?? config.order?.length ?? 0;
|
|
1318
|
+
return leftRank - rightRank;
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
if (config?.sort !== void 0) resolved.sort((left, right) => config.sort?.(left, right, context) ?? 0);
|
|
1322
|
+
return resolved;
|
|
1323
|
+
}
|
|
1294
1324
|
var BUILDER_DEFAULTS = {
|
|
1295
1325
|
"builder.formBuilder": "Form builder",
|
|
1296
1326
|
"builder.basicSettings": "Basic settings",
|
|
@@ -1309,6 +1339,10 @@ var BUILDER_DEFAULTS = {
|
|
|
1309
1339
|
"builder.required": "Required",
|
|
1310
1340
|
"builder.minimum": "Minimum",
|
|
1311
1341
|
"builder.maximum": "Maximum",
|
|
1342
|
+
"builder.minimumLength": "Minimum length",
|
|
1343
|
+
"builder.maximumLength": "Maximum length",
|
|
1344
|
+
"builder.pattern": "Pattern",
|
|
1345
|
+
"builder.step": "Step",
|
|
1312
1346
|
"builder.options": "Options",
|
|
1313
1347
|
"builder.optionLabel": "\u9078\u629E\u80A2 / Option Label {{index}}",
|
|
1314
1348
|
"builder.optionLabelPlaceholder": "Example: Very satisfied",
|
|
@@ -1566,6 +1600,8 @@ function FormBuilder({
|
|
|
1566
1600
|
createManualTranslationMetadata,
|
|
1567
1601
|
readOnly = false,
|
|
1568
1602
|
features,
|
|
1603
|
+
fieldEditorControls,
|
|
1604
|
+
fieldTypeOptions,
|
|
1569
1605
|
components: componentOverrides,
|
|
1570
1606
|
slots,
|
|
1571
1607
|
sectionOrder,
|
|
@@ -2330,6 +2366,7 @@ function FormBuilder({
|
|
|
2330
2366
|
}
|
|
2331
2367
|
) : null }),
|
|
2332
2368
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderSectionGroup, { name: "questions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__list"), children: schema.fields.map((field, index) => {
|
|
2369
|
+
const controls = resolveFieldEditorControls(fieldEditorControls);
|
|
2333
2370
|
const condition = field.displayCondition;
|
|
2334
2371
|
const source = condition === void 0 ? void 0 : schema.fields.find((item) => item.id === condition.questionId);
|
|
2335
2372
|
const availableSources = schema.fields.slice(0, index);
|
|
@@ -2345,6 +2382,8 @@ function FormBuilder({
|
|
|
2345
2382
|
...slots === void 0 ? {} : { slots },
|
|
2346
2383
|
...policy === void 0 ? {} : { policy },
|
|
2347
2384
|
...features === void 0 ? {} : { features },
|
|
2385
|
+
...fieldEditorControls === void 0 ? {} : { fieldEditorControls },
|
|
2386
|
+
...fieldTypeOptions === void 0 ? {} : { fieldTypeOptions },
|
|
2348
2387
|
readOnly,
|
|
2349
2388
|
actions,
|
|
2350
2389
|
components
|
|
@@ -2406,7 +2445,7 @@ function FormBuilder({
|
|
|
2406
2445
|
}
|
|
2407
2446
|
) }),
|
|
2408
2447
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2409
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2448
|
+
controls.title === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2410
2449
|
TextInput,
|
|
2411
2450
|
{
|
|
2412
2451
|
id: `builder-field-${field.id}-title`,
|
|
@@ -2418,34 +2457,56 @@ function FormBuilder({
|
|
|
2418
2457
|
"aria-describedby": field.title.trim().length === 0 ? `builder-field-${field.id}-title-error` : void 0,
|
|
2419
2458
|
value: field.title,
|
|
2420
2459
|
placeholder: translate("builder.questionTitlePlaceholder"),
|
|
2460
|
+
readOnly: controls.title === "readOnly",
|
|
2421
2461
|
onChange: (value) => updateField(field.id, (current) => ({
|
|
2422
2462
|
...current,
|
|
2423
2463
|
title: value.trim().length === 0 ? current.title : value
|
|
2424
2464
|
}))
|
|
2425
2465
|
}
|
|
2426
2466
|
) }),
|
|
2427
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2467
|
+
controls.typeSelect === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2428
2468
|
Select,
|
|
2429
2469
|
{
|
|
2430
2470
|
id: `builder-field-${field.id}-type`,
|
|
2431
2471
|
label: translate("builder.type"),
|
|
2432
2472
|
value: field.type,
|
|
2473
|
+
disabled: controls.typeSelect === "readOnly",
|
|
2433
2474
|
onChange: (value) => changeType(field.id, value),
|
|
2434
|
-
options:
|
|
2435
|
-
|
|
2436
|
-
|
|
2475
|
+
options: resolveFieldTypeSelectOptions(
|
|
2476
|
+
FIELD_TYPES.filter(
|
|
2477
|
+
(type) => policy?.allowedFieldTypes === void 0 || policy.allowedFieldTypes.includes(type)
|
|
2478
|
+
).map((type) => ({ value: type, label: translate(fieldTypeKey(type)) })),
|
|
2479
|
+
fieldTypeOptions,
|
|
2480
|
+
{ currentType: field.type, allowedTypes: policy?.allowedFieldTypes ?? FIELD_TYPES }
|
|
2481
|
+
)
|
|
2437
2482
|
}
|
|
2438
2483
|
) }),
|
|
2439
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2484
|
+
controls.required === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2440
2485
|
Checkbox,
|
|
2441
2486
|
{
|
|
2442
2487
|
className: builderClass("form-engine-builder__check"),
|
|
2443
2488
|
checked: field.required === true,
|
|
2489
|
+
disabled: controls.required === "readOnly",
|
|
2444
2490
|
onChange: (checked) => updateField(field.id, (current) => ({ ...current, required: checked })),
|
|
2445
2491
|
label: translate("builder.required")
|
|
2446
2492
|
}
|
|
2447
2493
|
)
|
|
2448
2494
|
] }),
|
|
2495
|
+
controls.description === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2496
|
+
TextArea,
|
|
2497
|
+
{
|
|
2498
|
+
id: `builder-field-${field.id}-description`,
|
|
2499
|
+
name: `fields.${field.id}.description`,
|
|
2500
|
+
label: translate("builder.description"),
|
|
2501
|
+
value: field.description ?? "",
|
|
2502
|
+
readOnly: controls.description === "readOnly",
|
|
2503
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2504
|
+
if (value.length > 0) return { ...current, description: value };
|
|
2505
|
+
const { description: _description, ...remaining } = current;
|
|
2506
|
+
return remaining;
|
|
2507
|
+
})
|
|
2508
|
+
}
|
|
2509
|
+
) }),
|
|
2449
2510
|
!pagesEnabled || schema.pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2450
2511
|
Select,
|
|
2451
2512
|
{
|
|
@@ -2481,12 +2542,13 @@ function FormBuilder({
|
|
|
2481
2542
|
})
|
|
2482
2543
|
}
|
|
2483
2544
|
) }),
|
|
2484
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2545
|
+
controls.description === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2485
2546
|
TextInput,
|
|
2486
2547
|
{
|
|
2487
2548
|
id: `builder-field-${field.id}-${editingLocale}-description`,
|
|
2488
2549
|
label: translate("builder.pageDescription"),
|
|
2489
2550
|
value: field.translations?.[editingLocale]?.description ?? "",
|
|
2551
|
+
readOnly: controls.description === "readOnly",
|
|
2490
2552
|
onChange: (value) => updateManualTranslation({
|
|
2491
2553
|
locale: editingLocale,
|
|
2492
2554
|
kind: "field",
|
|
@@ -2521,7 +2583,7 @@ function FormBuilder({
|
|
|
2521
2583
|
}
|
|
2522
2584
|
) }, option.id)) : null
|
|
2523
2585
|
] }),
|
|
2524
|
-
field.type === "rating" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2586
|
+
field.type === "rating" && controls.ratingBounds !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2525
2587
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2526
2588
|
TextInput,
|
|
2527
2589
|
{
|
|
@@ -2529,6 +2591,7 @@ function FormBuilder({
|
|
|
2529
2591
|
label: translate("builder.minimum"),
|
|
2530
2592
|
type: "number",
|
|
2531
2593
|
value: String(field.min ?? 1),
|
|
2594
|
+
readOnly: controls.ratingBounds === "readOnly",
|
|
2532
2595
|
onChange: (value) => {
|
|
2533
2596
|
const min = Number(value);
|
|
2534
2597
|
if (!Number.isInteger(min)) return;
|
|
@@ -2546,6 +2609,7 @@ function FormBuilder({
|
|
|
2546
2609
|
label: translate("builder.maximum"),
|
|
2547
2610
|
type: "number",
|
|
2548
2611
|
value: String(field.max ?? 5),
|
|
2612
|
+
readOnly: controls.ratingBounds === "readOnly",
|
|
2549
2613
|
onChange: (value) => {
|
|
2550
2614
|
const max = Number(value);
|
|
2551
2615
|
if (!Number.isInteger(max)) return;
|
|
@@ -2557,7 +2621,73 @@ function FormBuilder({
|
|
|
2557
2621
|
}
|
|
2558
2622
|
) })
|
|
2559
2623
|
] }) : null,
|
|
2560
|
-
"
|
|
2624
|
+
(field.type === "text" || field.type === "textarea") && controls.textLimits !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2625
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2626
|
+
TextInput,
|
|
2627
|
+
{
|
|
2628
|
+
id: `builder-field-${field.id}-min-length`,
|
|
2629
|
+
label: translate("builder.minimumLength"),
|
|
2630
|
+
type: "number",
|
|
2631
|
+
value: field.minLength === void 0 ? "" : String(field.minLength),
|
|
2632
|
+
readOnly: controls.textLimits === "readOnly",
|
|
2633
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2634
|
+
if (current.type !== "text" && current.type !== "textarea") return current;
|
|
2635
|
+
const parsed = value.trim().length === 0 ? void 0 : Number(value);
|
|
2636
|
+
return parsed === void 0 || !Number.isInteger(parsed) || parsed < 0 ? current : { ...current, minLength: parsed };
|
|
2637
|
+
})
|
|
2638
|
+
}
|
|
2639
|
+
) }),
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2641
|
+
TextInput,
|
|
2642
|
+
{
|
|
2643
|
+
id: `builder-field-${field.id}-max-length`,
|
|
2644
|
+
label: translate("builder.maximumLength"),
|
|
2645
|
+
type: "number",
|
|
2646
|
+
value: field.maxLength === void 0 ? "" : String(field.maxLength),
|
|
2647
|
+
readOnly: controls.textLimits === "readOnly",
|
|
2648
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2649
|
+
if (current.type !== "text" && current.type !== "textarea") return current;
|
|
2650
|
+
const parsed = value.trim().length === 0 ? void 0 : Number(value);
|
|
2651
|
+
return parsed === void 0 || !Number.isInteger(parsed) || parsed < 0 ? current : { ...current, maxLength: parsed };
|
|
2652
|
+
})
|
|
2653
|
+
}
|
|
2654
|
+
) }),
|
|
2655
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2656
|
+
TextInput,
|
|
2657
|
+
{
|
|
2658
|
+
id: `builder-field-${field.id}-pattern`,
|
|
2659
|
+
label: translate("builder.pattern"),
|
|
2660
|
+
value: field.pattern ?? "",
|
|
2661
|
+
readOnly: controls.textLimits === "readOnly",
|
|
2662
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2663
|
+
if (current.type !== "text" && current.type !== "textarea") return current;
|
|
2664
|
+
return value.length === 0 ? current : { ...current, pattern: value };
|
|
2665
|
+
})
|
|
2666
|
+
}
|
|
2667
|
+
) })
|
|
2668
|
+
] }) : null,
|
|
2669
|
+
field.type === "number" && controls.numberLimits !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__grid"), children: ["min", "max", "step"].map((property) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2670
|
+
TextInput,
|
|
2671
|
+
{
|
|
2672
|
+
id: `builder-field-${field.id}-${property}`,
|
|
2673
|
+
label: translate(
|
|
2674
|
+
property === "step" ? "builder.step" : property === "min" ? "builder.minimum" : "builder.maximum"
|
|
2675
|
+
),
|
|
2676
|
+
type: "number",
|
|
2677
|
+
value: field[property] === void 0 ? "" : String(field[property]),
|
|
2678
|
+
readOnly: controls.numberLimits === "readOnly",
|
|
2679
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2680
|
+
if (current.type !== "number") return current;
|
|
2681
|
+
if (value.trim().length === 0) {
|
|
2682
|
+
const { [property]: _removed, ...remaining } = current;
|
|
2683
|
+
return remaining;
|
|
2684
|
+
}
|
|
2685
|
+
const parsed = Number(value);
|
|
2686
|
+
return Number.isFinite(parsed) ? { ...current, [property]: parsed } : current;
|
|
2687
|
+
})
|
|
2688
|
+
}
|
|
2689
|
+
) }, property)) }) : null,
|
|
2690
|
+
"options" in field && controls.options !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__options"), children: [
|
|
2561
2691
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: translate("builder.options") }),
|
|
2562
2692
|
field.options.map(
|
|
2563
2693
|
(option, optionIndex) => OptionEditorSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__option"), children: [
|
|
@@ -2568,6 +2698,7 @@ function FormBuilder({
|
|
|
2568
2698
|
label: translate("builder.optionLabel", { index: optionIndex + 1 }),
|
|
2569
2699
|
value: option.label,
|
|
2570
2700
|
placeholder: translate("builder.optionLabelPlaceholder"),
|
|
2701
|
+
readOnly: controls.options === "readOnly",
|
|
2571
2702
|
onChange: (value) => value.trim().length === 0 ? void 0 : updateOption(field.id, option.id, value)
|
|
2572
2703
|
}
|
|
2573
2704
|
),
|
|
@@ -2577,7 +2708,7 @@ function FormBuilder({
|
|
|
2577
2708
|
{
|
|
2578
2709
|
actionType: "moveUp",
|
|
2579
2710
|
title: translate("builder.moveUp", { title: option.label }),
|
|
2580
|
-
disabled: optionIndex === 0,
|
|
2711
|
+
disabled: controls.options === "readOnly" || optionIndex === 0,
|
|
2581
2712
|
onClick: () => moveOption(field.id, option.id, optionIndex - 1)
|
|
2582
2713
|
}
|
|
2583
2714
|
),
|
|
@@ -2586,7 +2717,7 @@ function FormBuilder({
|
|
|
2586
2717
|
{
|
|
2587
2718
|
actionType: "moveDown",
|
|
2588
2719
|
title: translate("builder.moveDown", { title: option.label }),
|
|
2589
|
-
disabled: optionIndex === field.options.length - 1,
|
|
2720
|
+
disabled: controls.options === "readOnly" || optionIndex === field.options.length - 1,
|
|
2590
2721
|
onClick: () => moveOption(field.id, option.id, optionIndex + 1)
|
|
2591
2722
|
}
|
|
2592
2723
|
),
|
|
@@ -2594,7 +2725,7 @@ function FormBuilder({
|
|
|
2594
2725
|
IconButton,
|
|
2595
2726
|
{
|
|
2596
2727
|
actionType: "delete",
|
|
2597
|
-
disabled: field.options.length === 1,
|
|
2728
|
+
disabled: controls.options === "readOnly" || field.options.length === 1,
|
|
2598
2729
|
onClick: () => removeOption(field.id, option.id),
|
|
2599
2730
|
title: translate("builder.remove")
|
|
2600
2731
|
}
|
|
@@ -2612,7 +2743,7 @@ function FormBuilder({
|
|
|
2612
2743
|
onMoveUp: () => moveOption(field.id, option.id, optionIndex - 1),
|
|
2613
2744
|
onMoveDown: () => moveOption(field.id, option.id, optionIndex + 1),
|
|
2614
2745
|
onRemove: () => removeOption(field.id, option.id),
|
|
2615
|
-
readOnly,
|
|
2746
|
+
readOnly: readOnly || controls.options === "readOnly",
|
|
2616
2747
|
actions,
|
|
2617
2748
|
components
|
|
2618
2749
|
}
|
|
@@ -2626,7 +2757,7 @@ function FormBuilder({
|
|
|
2626
2757
|
index: optionIndex,
|
|
2627
2758
|
currentLocale: editingLocale,
|
|
2628
2759
|
translate,
|
|
2629
|
-
readOnly,
|
|
2760
|
+
readOnly: readOnly || controls.options === "readOnly",
|
|
2630
2761
|
actions,
|
|
2631
2762
|
components
|
|
2632
2763
|
},
|
|
@@ -2638,13 +2769,13 @@ function FormBuilder({
|
|
|
2638
2769
|
{
|
|
2639
2770
|
action: "addOption",
|
|
2640
2771
|
targetId: field.id,
|
|
2641
|
-
disabled: policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
|
|
2772
|
+
disabled: controls.options === "readOnly" || policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
|
|
2642
2773
|
onClick: () => addOption(field.id),
|
|
2643
2774
|
children: translate("builder.addOption")
|
|
2644
2775
|
}
|
|
2645
2776
|
)
|
|
2646
2777
|
] }) : null,
|
|
2647
|
-
conditionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__condition"), children: [
|
|
2778
|
+
conditionsEnabled && controls.displayConditions !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__condition"), children: [
|
|
2648
2779
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2649
2780
|
Select,
|
|
2650
2781
|
{
|
|
@@ -4001,6 +4132,8 @@ function FormRenderer(props) {
|
|
|
4001
4132
|
createLocalStorageSubmissionAttemptStore,
|
|
4002
4133
|
createLocalStorageSubmissionReceiptStore,
|
|
4003
4134
|
isTranslationUnresolved,
|
|
4135
|
+
resolveFieldEditorControls,
|
|
4136
|
+
resolveFieldTypeSelectOptions,
|
|
4004
4137
|
resolveInitialFieldType,
|
|
4005
4138
|
resolveTranslation,
|
|
4006
4139
|
submissionReceiptQueryKey,
|
package/dist/index.d.cts
CHANGED
|
@@ -192,6 +192,32 @@ interface BuilderSelectOption<T extends string = string> {
|
|
|
192
192
|
readonly kind?: string;
|
|
193
193
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
194
194
|
}
|
|
195
|
+
type FieldPropertyControlMode = "editable" | "readOnly" | "hidden";
|
|
196
|
+
interface FieldEditorControlsConfig {
|
|
197
|
+
readonly title?: FieldPropertyControlMode;
|
|
198
|
+
readonly description?: FieldPropertyControlMode;
|
|
199
|
+
readonly required?: FieldPropertyControlMode;
|
|
200
|
+
readonly typeSelect?: FieldPropertyControlMode;
|
|
201
|
+
readonly options?: FieldPropertyControlMode;
|
|
202
|
+
readonly displayConditions?: FieldPropertyControlMode;
|
|
203
|
+
readonly textLimits?: FieldPropertyControlMode;
|
|
204
|
+
readonly ratingBounds?: FieldPropertyControlMode;
|
|
205
|
+
readonly numberLimits?: FieldPropertyControlMode;
|
|
206
|
+
}
|
|
207
|
+
interface FieldTypeSelectOptionsContext {
|
|
208
|
+
readonly currentType: QuestionType;
|
|
209
|
+
readonly allowedTypes: readonly QuestionType[];
|
|
210
|
+
}
|
|
211
|
+
type FieldTypeSelectOptionsTransformer = (options: readonly BuilderSelectOption<QuestionType>[], context: FieldTypeSelectOptionsContext) => readonly BuilderSelectOption<QuestionType>[];
|
|
212
|
+
type FieldTypeSelectOptionsSorter = (left: BuilderSelectOption<QuestionType>, right: BuilderSelectOption<QuestionType>, context: FieldTypeSelectOptionsContext) => number;
|
|
213
|
+
interface FieldTypeSelectOptionsConfig {
|
|
214
|
+
/** Transform the generated choices. The returned array is used as-is. */
|
|
215
|
+
readonly transform?: FieldTypeSelectOptionsTransformer;
|
|
216
|
+
/** Sort generated choices after transform. The source array is never mutated. */
|
|
217
|
+
readonly sort?: FieldTypeSelectOptionsSorter;
|
|
218
|
+
/** Optional explicit order applied before `sort`. */
|
|
219
|
+
readonly order?: readonly QuestionType[];
|
|
220
|
+
}
|
|
195
221
|
interface SelectComponentProps<T extends string = string> extends Omit<InputComponentProps, "value" | "onChange"> {
|
|
196
222
|
readonly value: T;
|
|
197
223
|
readonly onChange: (value: T) => void;
|
|
@@ -278,6 +304,8 @@ interface BuilderFieldEditorSlotProps extends BuilderSlotBaseProps {
|
|
|
278
304
|
readonly localization?: boolean;
|
|
279
305
|
readonly conditions?: boolean;
|
|
280
306
|
};
|
|
307
|
+
readonly fieldEditorControls?: FieldEditorControlsConfig;
|
|
308
|
+
readonly fieldTypeOptions?: FieldTypeSelectOptionsConfig;
|
|
281
309
|
readonly slots?: Pick<FormBuilderSlots, "fieldTypeSelect" | "fieldEditorHeader">;
|
|
282
310
|
}
|
|
283
311
|
interface FieldTypeSelectSlotProps {
|
|
@@ -524,6 +552,8 @@ interface SubmissionProtectionProps {
|
|
|
524
552
|
}
|
|
525
553
|
type BeforeSubmit = (values: Readonly<Record<string, unknown>>) => "continue" | "cancel" | Promise<"continue" | "cancel">;
|
|
526
554
|
|
|
555
|
+
declare function resolveFieldEditorControls(config?: FieldEditorControlsConfig): Required<FieldEditorControlsConfig>;
|
|
556
|
+
declare function resolveFieldTypeSelectOptions(options: readonly BuilderSelectOption<QuestionType>[], config: FieldTypeSelectOptionsConfig | undefined, context: FieldTypeSelectOptionsContext): readonly BuilderSelectOption<QuestionType>[];
|
|
527
557
|
declare function resolveInitialFieldType(defaultType?: QuestionType, allowedTypes?: readonly QuestionType[]): QuestionType | null;
|
|
528
558
|
interface FormBuilderFeatures {
|
|
529
559
|
readonly pages?: boolean;
|
|
@@ -547,13 +577,15 @@ interface FormBuilderProps {
|
|
|
547
577
|
readonly createManualTranslationMetadata?: (context: ManualTranslationContext) => Readonly<Record<string, JsonValue>> | undefined;
|
|
548
578
|
readonly readOnly?: boolean;
|
|
549
579
|
readonly features?: FormBuilderFeatures;
|
|
580
|
+
readonly fieldEditorControls?: FieldEditorControlsConfig;
|
|
581
|
+
readonly fieldTypeOptions?: FieldTypeSelectOptionsConfig;
|
|
550
582
|
readonly components?: FormBuilderComponents;
|
|
551
583
|
readonly slots?: FormBuilderSlots;
|
|
552
584
|
readonly sectionOrder?: readonly FormBuilderSectionName[];
|
|
553
585
|
readonly disableDefaultStyles?: boolean;
|
|
554
586
|
readonly unstyled?: boolean;
|
|
555
587
|
}
|
|
556
|
-
declare function FormBuilder({ schema, onChange, locale, translator, translationAdapter, translationOptions, onTranslationReport, policy, idFactory, factories, className, defaultFieldType, onActionError, createManualTranslationMetadata, readOnly, features, components: componentOverrides, slots, sectionOrder, disableDefaultStyles, unstyled }: FormBuilderProps): react.JSX.Element;
|
|
588
|
+
declare function FormBuilder({ schema, onChange, locale, translator, translationAdapter, translationOptions, onTranslationReport, policy, idFactory, factories, className, defaultFieldType, onActionError, createManualTranslationMetadata, readOnly, features, fieldEditorControls, fieldTypeOptions, components: componentOverrides, slots, sectionOrder, disableDefaultStyles, unstyled }: FormBuilderProps): react.JSX.Element;
|
|
557
589
|
|
|
558
590
|
type SubmitStatus = "idle" | "submitting" | "success" | "error";
|
|
559
591
|
interface FormContextValue {
|
|
@@ -659,4 +691,4 @@ interface StandaloneFormRendererProps extends FormRendererPresentationProps {
|
|
|
659
691
|
type FormRendererProps = FormRendererPresentationProps | StandaloneFormRendererProps;
|
|
660
692
|
declare function FormRenderer(props: FormRendererProps): react.JSX.Element;
|
|
661
693
|
|
|
662
|
-
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ComponentBaseProps, type FieldComponentProps, type FieldComponents, type FieldEditorHeaderSlotProps, type FieldState, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormCompletionSlotProps, type FormContextValue, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type UseSubmissionReceiptsResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useSubmissionReceipts };
|
|
694
|
+
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ComponentBaseProps, type FieldComponentProps, type FieldComponents, type FieldEditorControlsConfig, type FieldEditorHeaderSlotProps, type FieldPropertyControlMode, type FieldState, type FieldTypeSelectOptionsConfig, type FieldTypeSelectOptionsContext, type FieldTypeSelectOptionsSorter, type FieldTypeSelectOptionsTransformer, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormCompletionSlotProps, type FormContextValue, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type UseSubmissionReceiptsResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveFieldEditorControls, resolveFieldTypeSelectOptions, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useSubmissionReceipts };
|
package/dist/index.d.ts
CHANGED
|
@@ -192,6 +192,32 @@ interface BuilderSelectOption<T extends string = string> {
|
|
|
192
192
|
readonly kind?: string;
|
|
193
193
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
194
194
|
}
|
|
195
|
+
type FieldPropertyControlMode = "editable" | "readOnly" | "hidden";
|
|
196
|
+
interface FieldEditorControlsConfig {
|
|
197
|
+
readonly title?: FieldPropertyControlMode;
|
|
198
|
+
readonly description?: FieldPropertyControlMode;
|
|
199
|
+
readonly required?: FieldPropertyControlMode;
|
|
200
|
+
readonly typeSelect?: FieldPropertyControlMode;
|
|
201
|
+
readonly options?: FieldPropertyControlMode;
|
|
202
|
+
readonly displayConditions?: FieldPropertyControlMode;
|
|
203
|
+
readonly textLimits?: FieldPropertyControlMode;
|
|
204
|
+
readonly ratingBounds?: FieldPropertyControlMode;
|
|
205
|
+
readonly numberLimits?: FieldPropertyControlMode;
|
|
206
|
+
}
|
|
207
|
+
interface FieldTypeSelectOptionsContext {
|
|
208
|
+
readonly currentType: QuestionType;
|
|
209
|
+
readonly allowedTypes: readonly QuestionType[];
|
|
210
|
+
}
|
|
211
|
+
type FieldTypeSelectOptionsTransformer = (options: readonly BuilderSelectOption<QuestionType>[], context: FieldTypeSelectOptionsContext) => readonly BuilderSelectOption<QuestionType>[];
|
|
212
|
+
type FieldTypeSelectOptionsSorter = (left: BuilderSelectOption<QuestionType>, right: BuilderSelectOption<QuestionType>, context: FieldTypeSelectOptionsContext) => number;
|
|
213
|
+
interface FieldTypeSelectOptionsConfig {
|
|
214
|
+
/** Transform the generated choices. The returned array is used as-is. */
|
|
215
|
+
readonly transform?: FieldTypeSelectOptionsTransformer;
|
|
216
|
+
/** Sort generated choices after transform. The source array is never mutated. */
|
|
217
|
+
readonly sort?: FieldTypeSelectOptionsSorter;
|
|
218
|
+
/** Optional explicit order applied before `sort`. */
|
|
219
|
+
readonly order?: readonly QuestionType[];
|
|
220
|
+
}
|
|
195
221
|
interface SelectComponentProps<T extends string = string> extends Omit<InputComponentProps, "value" | "onChange"> {
|
|
196
222
|
readonly value: T;
|
|
197
223
|
readonly onChange: (value: T) => void;
|
|
@@ -278,6 +304,8 @@ interface BuilderFieldEditorSlotProps extends BuilderSlotBaseProps {
|
|
|
278
304
|
readonly localization?: boolean;
|
|
279
305
|
readonly conditions?: boolean;
|
|
280
306
|
};
|
|
307
|
+
readonly fieldEditorControls?: FieldEditorControlsConfig;
|
|
308
|
+
readonly fieldTypeOptions?: FieldTypeSelectOptionsConfig;
|
|
281
309
|
readonly slots?: Pick<FormBuilderSlots, "fieldTypeSelect" | "fieldEditorHeader">;
|
|
282
310
|
}
|
|
283
311
|
interface FieldTypeSelectSlotProps {
|
|
@@ -524,6 +552,8 @@ interface SubmissionProtectionProps {
|
|
|
524
552
|
}
|
|
525
553
|
type BeforeSubmit = (values: Readonly<Record<string, unknown>>) => "continue" | "cancel" | Promise<"continue" | "cancel">;
|
|
526
554
|
|
|
555
|
+
declare function resolveFieldEditorControls(config?: FieldEditorControlsConfig): Required<FieldEditorControlsConfig>;
|
|
556
|
+
declare function resolveFieldTypeSelectOptions(options: readonly BuilderSelectOption<QuestionType>[], config: FieldTypeSelectOptionsConfig | undefined, context: FieldTypeSelectOptionsContext): readonly BuilderSelectOption<QuestionType>[];
|
|
527
557
|
declare function resolveInitialFieldType(defaultType?: QuestionType, allowedTypes?: readonly QuestionType[]): QuestionType | null;
|
|
528
558
|
interface FormBuilderFeatures {
|
|
529
559
|
readonly pages?: boolean;
|
|
@@ -547,13 +577,15 @@ interface FormBuilderProps {
|
|
|
547
577
|
readonly createManualTranslationMetadata?: (context: ManualTranslationContext) => Readonly<Record<string, JsonValue>> | undefined;
|
|
548
578
|
readonly readOnly?: boolean;
|
|
549
579
|
readonly features?: FormBuilderFeatures;
|
|
580
|
+
readonly fieldEditorControls?: FieldEditorControlsConfig;
|
|
581
|
+
readonly fieldTypeOptions?: FieldTypeSelectOptionsConfig;
|
|
550
582
|
readonly components?: FormBuilderComponents;
|
|
551
583
|
readonly slots?: FormBuilderSlots;
|
|
552
584
|
readonly sectionOrder?: readonly FormBuilderSectionName[];
|
|
553
585
|
readonly disableDefaultStyles?: boolean;
|
|
554
586
|
readonly unstyled?: boolean;
|
|
555
587
|
}
|
|
556
|
-
declare function FormBuilder({ schema, onChange, locale, translator, translationAdapter, translationOptions, onTranslationReport, policy, idFactory, factories, className, defaultFieldType, onActionError, createManualTranslationMetadata, readOnly, features, components: componentOverrides, slots, sectionOrder, disableDefaultStyles, unstyled }: FormBuilderProps): react.JSX.Element;
|
|
588
|
+
declare function FormBuilder({ schema, onChange, locale, translator, translationAdapter, translationOptions, onTranslationReport, policy, idFactory, factories, className, defaultFieldType, onActionError, createManualTranslationMetadata, readOnly, features, fieldEditorControls, fieldTypeOptions, components: componentOverrides, slots, sectionOrder, disableDefaultStyles, unstyled }: FormBuilderProps): react.JSX.Element;
|
|
557
589
|
|
|
558
590
|
type SubmitStatus = "idle" | "submitting" | "success" | "error";
|
|
559
591
|
interface FormContextValue {
|
|
@@ -659,4 +691,4 @@ interface StandaloneFormRendererProps extends FormRendererPresentationProps {
|
|
|
659
691
|
type FormRendererProps = FormRendererPresentationProps | StandaloneFormRendererProps;
|
|
660
692
|
declare function FormRenderer(props: FormRendererProps): react.JSX.Element;
|
|
661
693
|
|
|
662
|
-
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ComponentBaseProps, type FieldComponentProps, type FieldComponents, type FieldEditorHeaderSlotProps, type FieldState, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormCompletionSlotProps, type FormContextValue, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type UseSubmissionReceiptsResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useSubmissionReceipts };
|
|
694
|
+
export { BUILDER_TRANSLATION_ALIASES, BUILDER_TRANSLATION_KEYS, type BeforeSubmit, type BuilderActionContext, type BuilderActionError, type BuilderActionIconType, type BuilderActionResult, type BuilderButtonProps, type BuilderCheckboxProps, type BuilderErrorMessageProps, type BuilderFactories, type BuilderFieldEditorSlotProps, type BuilderFieldsetProps, type BuilderIconButtonProps, type BuilderIdKind, type BuilderLocalizationSlotProps, type BuilderOptionEditorSlotProps, type BuilderPagesSlotProps, type BuilderPolicy, type BuilderSectionProps, type BuilderSelectOption, type BuilderSelectProps, type BuilderSlotActions, type BuilderTextAreaProps, type BuilderTextInputProps, type BuilderTextTarget, type BuilderToolbarSlotProps, type BuilderTranslationActionsSlotProps, type BuilderTranslationKey, type ComponentBaseProps, type FieldComponentProps, type FieldComponents, type FieldEditorControlsConfig, type FieldEditorHeaderSlotProps, type FieldPropertyControlMode, type FieldState, type FieldTypeSelectOptionsConfig, type FieldTypeSelectOptionsContext, type FieldTypeSelectOptionsSorter, type FieldTypeSelectOptionsTransformer, type FieldTypeSelectSlotProps, FormBuilder, type FormBuilderActions, type FormBuilderComponents, type FormBuilderFeatures, type FormBuilderOptions, type FormBuilderProps, type FormBuilderResult, type FormBuilderSectionName, type FormBuilderSlots, type FormCompletionSlotProps, type FormContextValue, type FormFieldsSlotProps, FormProvider, type FormProviderProps, FormRenderer, type FormRendererMessages, type FormRendererPresentationProps, type FormRendererProps, type FormRendererSlots, type FormServerErrorPayload, FormSubmissionError, type FormSubmitHandler, type FormSubmitState, type FormSubmitStatus, type FormSubmittedAnswerItem, type FormSuccessRenderMode, type IconButtonProps, type InputComponentProps, type LocalizationSummaryContext, type ManualTranslationContext, type ManualTranslationTarget, type RenderSubmitButtonProps, type SelectComponentProps, type StandaloneFormRendererProps, type SubmissionAttempt, type SubmissionAttemptStore, type SubmissionConfirmationRenderMode, type SubmissionConfirmationSlotProps, type SubmissionGuard, type SubmissionGuardResult, type SubmissionProtectionProps, type SubmissionReceipt, type SubmissionReceiptQuery, type SubmissionReceiptStore, type SubmitContext, type SubmitResponse, type SubmitResult, type SubmitStatus, type UseSubmissionReceiptsResult, createLocalStorageSubmissionAttemptStore, createLocalStorageSubmissionReceiptStore, isTranslationUnresolved, resolveFieldEditorControls, resolveFieldTypeSelectOptions, resolveInitialFieldType, resolveTranslation, submissionReceiptQueryKey, useField, useForm, useFormBuilder, useSubmissionReceipts };
|
package/dist/index.js
CHANGED
|
@@ -1257,6 +1257,34 @@ var FIELD_TYPES = [
|
|
|
1257
1257
|
"checkbox",
|
|
1258
1258
|
"radio"
|
|
1259
1259
|
];
|
|
1260
|
+
var DEFAULT_FIELD_EDITOR_CONTROL_MODE = "editable";
|
|
1261
|
+
function resolveFieldEditorControls(config = {}) {
|
|
1262
|
+
return {
|
|
1263
|
+
title: config.title ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1264
|
+
description: config.description ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1265
|
+
required: config.required ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1266
|
+
typeSelect: config.typeSelect ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1267
|
+
options: config.options ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1268
|
+
displayConditions: config.displayConditions ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1269
|
+
textLimits: config.textLimits ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1270
|
+
ratingBounds: config.ratingBounds ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE,
|
|
1271
|
+
numberLimits: config.numberLimits ?? DEFAULT_FIELD_EDITOR_CONTROL_MODE
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
function resolveFieldTypeSelectOptions(options, config, context) {
|
|
1275
|
+
let resolved = [...options];
|
|
1276
|
+
if (config?.transform !== void 0) resolved = [...config.transform(resolved, context)];
|
|
1277
|
+
if (config?.order !== void 0) {
|
|
1278
|
+
const ranks = new Map(config.order.map((type, index) => [type, index]));
|
|
1279
|
+
resolved.sort((left, right) => {
|
|
1280
|
+
const leftRank = ranks.get(left.value) ?? config.order?.length ?? 0;
|
|
1281
|
+
const rightRank = ranks.get(right.value) ?? config.order?.length ?? 0;
|
|
1282
|
+
return leftRank - rightRank;
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
if (config?.sort !== void 0) resolved.sort((left, right) => config.sort?.(left, right, context) ?? 0);
|
|
1286
|
+
return resolved;
|
|
1287
|
+
}
|
|
1260
1288
|
var BUILDER_DEFAULTS = {
|
|
1261
1289
|
"builder.formBuilder": "Form builder",
|
|
1262
1290
|
"builder.basicSettings": "Basic settings",
|
|
@@ -1275,6 +1303,10 @@ var BUILDER_DEFAULTS = {
|
|
|
1275
1303
|
"builder.required": "Required",
|
|
1276
1304
|
"builder.minimum": "Minimum",
|
|
1277
1305
|
"builder.maximum": "Maximum",
|
|
1306
|
+
"builder.minimumLength": "Minimum length",
|
|
1307
|
+
"builder.maximumLength": "Maximum length",
|
|
1308
|
+
"builder.pattern": "Pattern",
|
|
1309
|
+
"builder.step": "Step",
|
|
1278
1310
|
"builder.options": "Options",
|
|
1279
1311
|
"builder.optionLabel": "\u9078\u629E\u80A2 / Option Label {{index}}",
|
|
1280
1312
|
"builder.optionLabelPlaceholder": "Example: Very satisfied",
|
|
@@ -1532,6 +1564,8 @@ function FormBuilder({
|
|
|
1532
1564
|
createManualTranslationMetadata,
|
|
1533
1565
|
readOnly = false,
|
|
1534
1566
|
features,
|
|
1567
|
+
fieldEditorControls,
|
|
1568
|
+
fieldTypeOptions,
|
|
1535
1569
|
components: componentOverrides,
|
|
1536
1570
|
slots,
|
|
1537
1571
|
sectionOrder,
|
|
@@ -2296,6 +2330,7 @@ function FormBuilder({
|
|
|
2296
2330
|
}
|
|
2297
2331
|
) : null }),
|
|
2298
2332
|
/* @__PURE__ */ jsx(BuilderSectionGroup, { name: "questions", children: /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__list"), children: schema.fields.map((field, index) => {
|
|
2333
|
+
const controls = resolveFieldEditorControls(fieldEditorControls);
|
|
2299
2334
|
const condition = field.displayCondition;
|
|
2300
2335
|
const source = condition === void 0 ? void 0 : schema.fields.find((item) => item.id === condition.questionId);
|
|
2301
2336
|
const availableSources = schema.fields.slice(0, index);
|
|
@@ -2311,6 +2346,8 @@ function FormBuilder({
|
|
|
2311
2346
|
...slots === void 0 ? {} : { slots },
|
|
2312
2347
|
...policy === void 0 ? {} : { policy },
|
|
2313
2348
|
...features === void 0 ? {} : { features },
|
|
2349
|
+
...fieldEditorControls === void 0 ? {} : { fieldEditorControls },
|
|
2350
|
+
...fieldTypeOptions === void 0 ? {} : { fieldTypeOptions },
|
|
2314
2351
|
readOnly,
|
|
2315
2352
|
actions,
|
|
2316
2353
|
components
|
|
@@ -2372,7 +2409,7 @@ function FormBuilder({
|
|
|
2372
2409
|
}
|
|
2373
2410
|
) }),
|
|
2374
2411
|
/* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2375
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2412
|
+
controls.title === "hidden" ? null : /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2376
2413
|
TextInput,
|
|
2377
2414
|
{
|
|
2378
2415
|
id: `builder-field-${field.id}-title`,
|
|
@@ -2384,34 +2421,56 @@ function FormBuilder({
|
|
|
2384
2421
|
"aria-describedby": field.title.trim().length === 0 ? `builder-field-${field.id}-title-error` : void 0,
|
|
2385
2422
|
value: field.title,
|
|
2386
2423
|
placeholder: translate("builder.questionTitlePlaceholder"),
|
|
2424
|
+
readOnly: controls.title === "readOnly",
|
|
2387
2425
|
onChange: (value) => updateField(field.id, (current) => ({
|
|
2388
2426
|
...current,
|
|
2389
2427
|
title: value.trim().length === 0 ? current.title : value
|
|
2390
2428
|
}))
|
|
2391
2429
|
}
|
|
2392
2430
|
) }),
|
|
2393
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2431
|
+
controls.typeSelect === "hidden" ? null : /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2394
2432
|
Select,
|
|
2395
2433
|
{
|
|
2396
2434
|
id: `builder-field-${field.id}-type`,
|
|
2397
2435
|
label: translate("builder.type"),
|
|
2398
2436
|
value: field.type,
|
|
2437
|
+
disabled: controls.typeSelect === "readOnly",
|
|
2399
2438
|
onChange: (value) => changeType(field.id, value),
|
|
2400
|
-
options:
|
|
2401
|
-
|
|
2402
|
-
|
|
2439
|
+
options: resolveFieldTypeSelectOptions(
|
|
2440
|
+
FIELD_TYPES.filter(
|
|
2441
|
+
(type) => policy?.allowedFieldTypes === void 0 || policy.allowedFieldTypes.includes(type)
|
|
2442
|
+
).map((type) => ({ value: type, label: translate(fieldTypeKey(type)) })),
|
|
2443
|
+
fieldTypeOptions,
|
|
2444
|
+
{ currentType: field.type, allowedTypes: policy?.allowedFieldTypes ?? FIELD_TYPES }
|
|
2445
|
+
)
|
|
2403
2446
|
}
|
|
2404
2447
|
) }),
|
|
2405
|
-
/* @__PURE__ */ jsx(
|
|
2448
|
+
controls.required === "hidden" ? null : /* @__PURE__ */ jsx(
|
|
2406
2449
|
Checkbox,
|
|
2407
2450
|
{
|
|
2408
2451
|
className: builderClass("form-engine-builder__check"),
|
|
2409
2452
|
checked: field.required === true,
|
|
2453
|
+
disabled: controls.required === "readOnly",
|
|
2410
2454
|
onChange: (checked) => updateField(field.id, (current) => ({ ...current, required: checked })),
|
|
2411
2455
|
label: translate("builder.required")
|
|
2412
2456
|
}
|
|
2413
2457
|
)
|
|
2414
2458
|
] }),
|
|
2459
|
+
controls.description === "hidden" ? null : /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2460
|
+
TextArea,
|
|
2461
|
+
{
|
|
2462
|
+
id: `builder-field-${field.id}-description`,
|
|
2463
|
+
name: `fields.${field.id}.description`,
|
|
2464
|
+
label: translate("builder.description"),
|
|
2465
|
+
value: field.description ?? "",
|
|
2466
|
+
readOnly: controls.description === "readOnly",
|
|
2467
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2468
|
+
if (value.length > 0) return { ...current, description: value };
|
|
2469
|
+
const { description: _description, ...remaining } = current;
|
|
2470
|
+
return remaining;
|
|
2471
|
+
})
|
|
2472
|
+
}
|
|
2473
|
+
) }),
|
|
2415
2474
|
!pagesEnabled || schema.pages === void 0 ? null : /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2416
2475
|
Select,
|
|
2417
2476
|
{
|
|
@@ -2447,12 +2506,13 @@ function FormBuilder({
|
|
|
2447
2506
|
})
|
|
2448
2507
|
}
|
|
2449
2508
|
) }),
|
|
2450
|
-
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2509
|
+
controls.description === "hidden" ? null : /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2451
2510
|
TextInput,
|
|
2452
2511
|
{
|
|
2453
2512
|
id: `builder-field-${field.id}-${editingLocale}-description`,
|
|
2454
2513
|
label: translate("builder.pageDescription"),
|
|
2455
2514
|
value: field.translations?.[editingLocale]?.description ?? "",
|
|
2515
|
+
readOnly: controls.description === "readOnly",
|
|
2456
2516
|
onChange: (value) => updateManualTranslation({
|
|
2457
2517
|
locale: editingLocale,
|
|
2458
2518
|
kind: "field",
|
|
@@ -2487,7 +2547,7 @@ function FormBuilder({
|
|
|
2487
2547
|
}
|
|
2488
2548
|
) }, option.id)) : null
|
|
2489
2549
|
] }),
|
|
2490
|
-
field.type === "rating" ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2550
|
+
field.type === "rating" && controls.ratingBounds !== "hidden" ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2491
2551
|
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2492
2552
|
TextInput,
|
|
2493
2553
|
{
|
|
@@ -2495,6 +2555,7 @@ function FormBuilder({
|
|
|
2495
2555
|
label: translate("builder.minimum"),
|
|
2496
2556
|
type: "number",
|
|
2497
2557
|
value: String(field.min ?? 1),
|
|
2558
|
+
readOnly: controls.ratingBounds === "readOnly",
|
|
2498
2559
|
onChange: (value) => {
|
|
2499
2560
|
const min = Number(value);
|
|
2500
2561
|
if (!Number.isInteger(min)) return;
|
|
@@ -2512,6 +2573,7 @@ function FormBuilder({
|
|
|
2512
2573
|
label: translate("builder.maximum"),
|
|
2513
2574
|
type: "number",
|
|
2514
2575
|
value: String(field.max ?? 5),
|
|
2576
|
+
readOnly: controls.ratingBounds === "readOnly",
|
|
2515
2577
|
onChange: (value) => {
|
|
2516
2578
|
const max = Number(value);
|
|
2517
2579
|
if (!Number.isInteger(max)) return;
|
|
@@ -2523,7 +2585,73 @@ function FormBuilder({
|
|
|
2523
2585
|
}
|
|
2524
2586
|
) })
|
|
2525
2587
|
] }) : null,
|
|
2526
|
-
"
|
|
2588
|
+
(field.type === "text" || field.type === "textarea") && controls.textLimits !== "hidden" ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__grid"), children: [
|
|
2589
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2590
|
+
TextInput,
|
|
2591
|
+
{
|
|
2592
|
+
id: `builder-field-${field.id}-min-length`,
|
|
2593
|
+
label: translate("builder.minimumLength"),
|
|
2594
|
+
type: "number",
|
|
2595
|
+
value: field.minLength === void 0 ? "" : String(field.minLength),
|
|
2596
|
+
readOnly: controls.textLimits === "readOnly",
|
|
2597
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2598
|
+
if (current.type !== "text" && current.type !== "textarea") return current;
|
|
2599
|
+
const parsed = value.trim().length === 0 ? void 0 : Number(value);
|
|
2600
|
+
return parsed === void 0 || !Number.isInteger(parsed) || parsed < 0 ? current : { ...current, minLength: parsed };
|
|
2601
|
+
})
|
|
2602
|
+
}
|
|
2603
|
+
) }),
|
|
2604
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2605
|
+
TextInput,
|
|
2606
|
+
{
|
|
2607
|
+
id: `builder-field-${field.id}-max-length`,
|
|
2608
|
+
label: translate("builder.maximumLength"),
|
|
2609
|
+
type: "number",
|
|
2610
|
+
value: field.maxLength === void 0 ? "" : String(field.maxLength),
|
|
2611
|
+
readOnly: controls.textLimits === "readOnly",
|
|
2612
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2613
|
+
if (current.type !== "text" && current.type !== "textarea") return current;
|
|
2614
|
+
const parsed = value.trim().length === 0 ? void 0 : Number(value);
|
|
2615
|
+
return parsed === void 0 || !Number.isInteger(parsed) || parsed < 0 ? current : { ...current, maxLength: parsed };
|
|
2616
|
+
})
|
|
2617
|
+
}
|
|
2618
|
+
) }),
|
|
2619
|
+
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2620
|
+
TextInput,
|
|
2621
|
+
{
|
|
2622
|
+
id: `builder-field-${field.id}-pattern`,
|
|
2623
|
+
label: translate("builder.pattern"),
|
|
2624
|
+
value: field.pattern ?? "",
|
|
2625
|
+
readOnly: controls.textLimits === "readOnly",
|
|
2626
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2627
|
+
if (current.type !== "text" && current.type !== "textarea") return current;
|
|
2628
|
+
return value.length === 0 ? current : { ...current, pattern: value };
|
|
2629
|
+
})
|
|
2630
|
+
}
|
|
2631
|
+
) })
|
|
2632
|
+
] }) : null,
|
|
2633
|
+
field.type === "number" && controls.numberLimits !== "hidden" ? /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__grid"), children: ["min", "max", "step"].map((property) => /* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2634
|
+
TextInput,
|
|
2635
|
+
{
|
|
2636
|
+
id: `builder-field-${field.id}-${property}`,
|
|
2637
|
+
label: translate(
|
|
2638
|
+
property === "step" ? "builder.step" : property === "min" ? "builder.minimum" : "builder.maximum"
|
|
2639
|
+
),
|
|
2640
|
+
type: "number",
|
|
2641
|
+
value: field[property] === void 0 ? "" : String(field[property]),
|
|
2642
|
+
readOnly: controls.numberLimits === "readOnly",
|
|
2643
|
+
onChange: (value) => updateField(field.id, (current) => {
|
|
2644
|
+
if (current.type !== "number") return current;
|
|
2645
|
+
if (value.trim().length === 0) {
|
|
2646
|
+
const { [property]: _removed, ...remaining } = current;
|
|
2647
|
+
return remaining;
|
|
2648
|
+
}
|
|
2649
|
+
const parsed = Number(value);
|
|
2650
|
+
return Number.isFinite(parsed) ? { ...current, [property]: parsed } : current;
|
|
2651
|
+
})
|
|
2652
|
+
}
|
|
2653
|
+
) }, property)) }) : null,
|
|
2654
|
+
"options" in field && controls.options !== "hidden" ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__options"), children: [
|
|
2527
2655
|
/* @__PURE__ */ jsx("strong", { children: translate("builder.options") }),
|
|
2528
2656
|
field.options.map(
|
|
2529
2657
|
(option, optionIndex) => OptionEditorSlot === void 0 ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__option"), children: [
|
|
@@ -2534,6 +2662,7 @@ function FormBuilder({
|
|
|
2534
2662
|
label: translate("builder.optionLabel", { index: optionIndex + 1 }),
|
|
2535
2663
|
value: option.label,
|
|
2536
2664
|
placeholder: translate("builder.optionLabelPlaceholder"),
|
|
2665
|
+
readOnly: controls.options === "readOnly",
|
|
2537
2666
|
onChange: (value) => value.trim().length === 0 ? void 0 : updateOption(field.id, option.id, value)
|
|
2538
2667
|
}
|
|
2539
2668
|
),
|
|
@@ -2543,7 +2672,7 @@ function FormBuilder({
|
|
|
2543
2672
|
{
|
|
2544
2673
|
actionType: "moveUp",
|
|
2545
2674
|
title: translate("builder.moveUp", { title: option.label }),
|
|
2546
|
-
disabled: optionIndex === 0,
|
|
2675
|
+
disabled: controls.options === "readOnly" || optionIndex === 0,
|
|
2547
2676
|
onClick: () => moveOption(field.id, option.id, optionIndex - 1)
|
|
2548
2677
|
}
|
|
2549
2678
|
),
|
|
@@ -2552,7 +2681,7 @@ function FormBuilder({
|
|
|
2552
2681
|
{
|
|
2553
2682
|
actionType: "moveDown",
|
|
2554
2683
|
title: translate("builder.moveDown", { title: option.label }),
|
|
2555
|
-
disabled: optionIndex === field.options.length - 1,
|
|
2684
|
+
disabled: controls.options === "readOnly" || optionIndex === field.options.length - 1,
|
|
2556
2685
|
onClick: () => moveOption(field.id, option.id, optionIndex + 1)
|
|
2557
2686
|
}
|
|
2558
2687
|
),
|
|
@@ -2560,7 +2689,7 @@ function FormBuilder({
|
|
|
2560
2689
|
IconButton,
|
|
2561
2690
|
{
|
|
2562
2691
|
actionType: "delete",
|
|
2563
|
-
disabled: field.options.length === 1,
|
|
2692
|
+
disabled: controls.options === "readOnly" || field.options.length === 1,
|
|
2564
2693
|
onClick: () => removeOption(field.id, option.id),
|
|
2565
2694
|
title: translate("builder.remove")
|
|
2566
2695
|
}
|
|
@@ -2578,7 +2707,7 @@ function FormBuilder({
|
|
|
2578
2707
|
onMoveUp: () => moveOption(field.id, option.id, optionIndex - 1),
|
|
2579
2708
|
onMoveDown: () => moveOption(field.id, option.id, optionIndex + 1),
|
|
2580
2709
|
onRemove: () => removeOption(field.id, option.id),
|
|
2581
|
-
readOnly,
|
|
2710
|
+
readOnly: readOnly || controls.options === "readOnly",
|
|
2582
2711
|
actions,
|
|
2583
2712
|
components
|
|
2584
2713
|
}
|
|
@@ -2592,7 +2721,7 @@ function FormBuilder({
|
|
|
2592
2721
|
index: optionIndex,
|
|
2593
2722
|
currentLocale: editingLocale,
|
|
2594
2723
|
translate,
|
|
2595
|
-
readOnly,
|
|
2724
|
+
readOnly: readOnly || controls.options === "readOnly",
|
|
2596
2725
|
actions,
|
|
2597
2726
|
components
|
|
2598
2727
|
},
|
|
@@ -2604,13 +2733,13 @@ function FormBuilder({
|
|
|
2604
2733
|
{
|
|
2605
2734
|
action: "addOption",
|
|
2606
2735
|
targetId: field.id,
|
|
2607
|
-
disabled: policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
|
|
2736
|
+
disabled: controls.options === "readOnly" || policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
|
|
2608
2737
|
onClick: () => addOption(field.id),
|
|
2609
2738
|
children: translate("builder.addOption")
|
|
2610
2739
|
}
|
|
2611
2740
|
)
|
|
2612
2741
|
] }) : null,
|
|
2613
|
-
conditionsEnabled ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__condition"), children: [
|
|
2742
|
+
conditionsEnabled && controls.displayConditions !== "hidden" ? /* @__PURE__ */ jsxs("div", { className: builderClass("form-engine-builder__condition"), children: [
|
|
2614
2743
|
/* @__PURE__ */ jsx("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ jsx(
|
|
2615
2744
|
Select,
|
|
2616
2745
|
{
|
|
@@ -3985,6 +4114,8 @@ export {
|
|
|
3985
4114
|
createLocalStorageSubmissionAttemptStore,
|
|
3986
4115
|
createLocalStorageSubmissionReceiptStore,
|
|
3987
4116
|
isTranslationUnresolved,
|
|
4117
|
+
resolveFieldEditorControls,
|
|
4118
|
+
resolveFieldTypeSelectOptions,
|
|
3988
4119
|
resolveInitialFieldType,
|
|
3989
4120
|
resolveTranslation,
|
|
3990
4121
|
submissionReceiptQueryKey,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@form-engine-ts/react",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"typescript"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@form-engine-ts/core": "4.
|
|
46
|
-
"@form-engine-ts/privacy": "4.
|
|
45
|
+
"@form-engine-ts/core": "4.1.0",
|
|
46
|
+
"@form-engine-ts/privacy": "4.1.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"react": ">=18.2 <20",
|