@form-engine-ts/mui 2.9.6 → 3.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 +24 -4
- package/dist/index.cjs +230 -71
- package/dist/index.d.cts +38 -5
- package/dist/index.d.ts +38 -5
- package/dist/index.js +264 -80
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -9,8 +9,15 @@ var DEFAULT_MUI_SECTION_ORDER = [
|
|
|
9
9
|
"basicSettings",
|
|
10
10
|
"questions",
|
|
11
11
|
"addQuestion",
|
|
12
|
-
"localization"
|
|
12
|
+
"localization",
|
|
13
|
+
"completionMessage"
|
|
13
14
|
];
|
|
15
|
+
var MUI_LOCALIZATION_SECTION_ORDERS = {
|
|
16
|
+
top: ["localization", "basicSettings", "completionMessage", "questions", "addQuestion"],
|
|
17
|
+
beforeQuestions: ["basicSettings", "localization", "completionMessage", "questions", "addQuestion"],
|
|
18
|
+
afterQuestions: ["basicSettings", "questions", "addQuestion", "localization", "completionMessage"],
|
|
19
|
+
bottom: ["basicSettings", "completionMessage", "questions", "addQuestion", "localization"]
|
|
20
|
+
};
|
|
14
21
|
function resolveMuiAdapterOptions(options = {}) {
|
|
15
22
|
const buttonVariant = options.buttonVariant ?? "contained";
|
|
16
23
|
return {
|
|
@@ -36,8 +43,13 @@ function resolveMuiAdapterOptions(options = {}) {
|
|
|
36
43
|
collapsible: options.localizationOptions?.collapsible ?? false,
|
|
37
44
|
defaultExpanded: options.localizationOptions?.defaultExpanded ?? false,
|
|
38
45
|
showSummary: options.localizationOptions?.showSummary ?? false,
|
|
46
|
+
...options.localizationOptions?.availableLocales === void 0 ? {} : { availableLocales: options.localizationOptions.availableLocales },
|
|
47
|
+
...options.localizationOptions?.placement === void 0 ? {} : { placement: options.localizationOptions.placement },
|
|
48
|
+
...options.localizationOptions?.renderSummary === void 0 ? {} : { renderSummary: options.localizationOptions.renderSummary },
|
|
39
49
|
...options.localizationOptions?.emptyStateMessage === void 0 ? {} : { emptyStateMessage: options.localizationOptions.emptyStateMessage },
|
|
40
|
-
defaultLocaleControl: options.localizationOptions?.defaultLocaleControl ?? "editable"
|
|
50
|
+
defaultLocaleControl: options.localizationOptions?.defaultLocaleControl ?? "editable",
|
|
51
|
+
noWrapActions: options.localizationOptions?.noWrapActions ?? true,
|
|
52
|
+
autoFocusNewTab: options.localizationOptions?.autoFocusNewTab ?? true
|
|
41
53
|
},
|
|
42
54
|
muiSlotProps: options.muiSlotProps ?? {}
|
|
43
55
|
};
|
|
@@ -75,6 +87,7 @@ function createMuiButtonAdapter(options) {
|
|
|
75
87
|
"aria-describedby": ariaDescribedBy,
|
|
76
88
|
"aria-labelledby": ariaLabelledBy,
|
|
77
89
|
onClick,
|
|
90
|
+
noWrap,
|
|
78
91
|
children,
|
|
79
92
|
title,
|
|
80
93
|
variant,
|
|
@@ -82,9 +95,11 @@ function createMuiButtonAdapter(options) {
|
|
|
82
95
|
targetId
|
|
83
96
|
}) {
|
|
84
97
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
98
|
+
const buttonSlotProps = resolved.muiSlotProps?.button;
|
|
85
99
|
return /* @__PURE__ */ jsx(
|
|
86
100
|
Button,
|
|
87
101
|
{
|
|
102
|
+
...buttonSlotProps,
|
|
88
103
|
id,
|
|
89
104
|
className,
|
|
90
105
|
type: "button",
|
|
@@ -98,9 +113,9 @@ function createMuiButtonAdapter(options) {
|
|
|
98
113
|
"data-target-id": targetId,
|
|
99
114
|
onClick,
|
|
100
115
|
color: variant === "danger" ? "error" : "primary",
|
|
101
|
-
variant: resolved.buttonVariants?.[variant ?? "primary"] ?? resolved.buttonVariant,
|
|
116
|
+
variant: buttonSlotProps?.variant ?? resolved.buttonVariants?.[variant ?? "primary"] ?? resolved.buttonVariant,
|
|
102
117
|
fullWidth: resolved.buttonFullWidth ?? false,
|
|
103
|
-
sx: { whiteSpace: "nowrap" },
|
|
118
|
+
sx: { whiteSpace: noWrap === false ? "normal" : "nowrap" },
|
|
104
119
|
children
|
|
105
120
|
}
|
|
106
121
|
);
|
|
@@ -129,6 +144,7 @@ function createMuiCheckboxAdapter(options) {
|
|
|
129
144
|
label
|
|
130
145
|
}) {
|
|
131
146
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
147
|
+
const checkboxSlotProps = resolved.muiSlotProps?.checkbox;
|
|
132
148
|
const helperId = id === void 0 ? void 0 : ariaDescribedBy?.split(/\s+/u)[0] ?? `${id}-helper-text`;
|
|
133
149
|
const describedBy = ariaDescribedBy ?? (helperText === void 0 || helperText.length === 0 ? void 0 : helperId);
|
|
134
150
|
return /* @__PURE__ */ jsxs(FormControl, { className, error: Boolean(error), required, disabled: disabled || readOnly, children: [
|
|
@@ -139,9 +155,10 @@ function createMuiCheckboxAdapter(options) {
|
|
|
139
155
|
control: /* @__PURE__ */ jsx2(
|
|
140
156
|
Checkbox,
|
|
141
157
|
{
|
|
158
|
+
...checkboxSlotProps,
|
|
142
159
|
id,
|
|
143
160
|
name,
|
|
144
|
-
size: resolved.size,
|
|
161
|
+
size: checkboxSlotProps?.size ?? resolved.size,
|
|
145
162
|
checked,
|
|
146
163
|
required,
|
|
147
164
|
disabled: disabled || readOnly,
|
|
@@ -253,16 +270,18 @@ function createMuiIconButtonAdapter(options) {
|
|
|
253
270
|
title
|
|
254
271
|
}) {
|
|
255
272
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
273
|
+
const iconButtonSlotProps = resolved.muiSlotProps?.iconButton;
|
|
256
274
|
const actionLabel = actionType === void 0 ? "Action" : resolved.getActionLabel?.(actionType) ?? FALLBACK_ACTION_LABELS[actionType];
|
|
257
275
|
const tooltip = title ?? actionLabel;
|
|
258
276
|
const color = actionType === "delete" ? "error" : actionType === "add" ? "primary" : "default";
|
|
259
277
|
return /* @__PURE__ */ jsx5(Tooltip, { title: tooltip, children: /* @__PURE__ */ jsx5("span", { children: /* @__PURE__ */ jsx5(
|
|
260
278
|
IconButton,
|
|
261
279
|
{
|
|
280
|
+
...iconButtonSlotProps,
|
|
262
281
|
id,
|
|
263
282
|
className,
|
|
264
283
|
type: "button",
|
|
265
|
-
size: resolved.size,
|
|
284
|
+
size: iconButtonSlotProps?.size ?? resolved.size,
|
|
266
285
|
color,
|
|
267
286
|
disabled: disabled || readOnly,
|
|
268
287
|
"aria-label": ariaLabel ?? tooltip,
|
|
@@ -326,8 +345,20 @@ function createMuiSectionAdapter(options) {
|
|
|
326
345
|
var MuiSectionAdapter = createMuiSectionAdapter();
|
|
327
346
|
|
|
328
347
|
// src/adapters/Select.tsx
|
|
329
|
-
import {
|
|
330
|
-
|
|
348
|
+
import {
|
|
349
|
+
Box as Box2,
|
|
350
|
+
FormControl as FormControl2,
|
|
351
|
+
FormHelperText as FormHelperText2,
|
|
352
|
+
InputLabel,
|
|
353
|
+
ListItemIcon,
|
|
354
|
+
ListItemText,
|
|
355
|
+
MenuItem,
|
|
356
|
+
Select
|
|
357
|
+
} from "@mui/material";
|
|
358
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
359
|
+
function normalizeOptions(options) {
|
|
360
|
+
return options.map((option) => typeof option === "string" ? { value: option, label: option } : option);
|
|
361
|
+
}
|
|
331
362
|
function createMuiSelectAdapter(options) {
|
|
332
363
|
return function MuiSelect({
|
|
333
364
|
id,
|
|
@@ -344,13 +375,19 @@ function createMuiSelectAdapter(options) {
|
|
|
344
375
|
helperText,
|
|
345
376
|
value,
|
|
346
377
|
onChange,
|
|
347
|
-
|
|
378
|
+
onKeyDown,
|
|
379
|
+
options: selectOptions,
|
|
380
|
+
renderOption,
|
|
381
|
+
renderValue
|
|
348
382
|
}) {
|
|
349
383
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
384
|
+
const normalizedOptions = normalizeOptions(selectOptions);
|
|
385
|
+
const selectSlotProps = resolved.muiSlotProps?.select;
|
|
386
|
+
const menuProps = { ...selectSlotProps?.MenuProps, ...resolved.muiSlotProps?.selectMenu };
|
|
350
387
|
const labelId = id === void 0 || label === void 0 ? void 0 : `${id}-label`;
|
|
351
388
|
const helperId = id === void 0 ? void 0 : ariaDescribedBy?.split(/\s+/u)[0] ?? `${id}-helper-text`;
|
|
352
389
|
const describedBy = ariaDescribedBy ?? (helperText === void 0 || helperText.length === 0 ? void 0 : helperId);
|
|
353
|
-
const handleChange = (event) => onChange(event.target.value);
|
|
390
|
+
const handleChange = (event) => onChange(String(event.target.value));
|
|
354
391
|
return /* @__PURE__ */ jsxs4(
|
|
355
392
|
FormControl2,
|
|
356
393
|
{
|
|
@@ -366,20 +403,39 @@ function createMuiSelectAdapter(options) {
|
|
|
366
403
|
/* @__PURE__ */ jsx7(
|
|
367
404
|
Select,
|
|
368
405
|
{
|
|
406
|
+
...selectSlotProps,
|
|
369
407
|
id,
|
|
370
408
|
labelId,
|
|
371
409
|
name,
|
|
372
410
|
label,
|
|
373
411
|
value,
|
|
412
|
+
disabled,
|
|
374
413
|
onChange: handleChange,
|
|
414
|
+
onKeyDown,
|
|
375
415
|
required,
|
|
376
416
|
readOnly,
|
|
417
|
+
variant: selectSlotProps?.variant ?? resolved.variant,
|
|
418
|
+
...Object.keys(menuProps).length === 0 ? {} : { MenuProps: menuProps },
|
|
419
|
+
renderValue: (selected) => {
|
|
420
|
+
const selectedValue = typeof selected === "string" ? selected : String(selected ?? "");
|
|
421
|
+
const option = normalizedOptions.find((candidate) => candidate.value === selectedValue);
|
|
422
|
+
if (renderValue !== void 0) return renderValue(option);
|
|
423
|
+
if (option === void 0) return selectedValue;
|
|
424
|
+
return /* @__PURE__ */ jsxs4(Box2, { display: "flex", alignItems: "center", gap: 0.75, children: [
|
|
425
|
+
option.icon,
|
|
426
|
+
/* @__PURE__ */ jsx7("span", { children: option.label })
|
|
427
|
+
] });
|
|
428
|
+
},
|
|
377
429
|
inputProps: {
|
|
430
|
+
...selectSlotProps?.inputProps,
|
|
378
431
|
"aria-label": ariaLabel,
|
|
379
432
|
"aria-describedby": describedBy,
|
|
380
433
|
"aria-labelledby": ariaLabelledBy
|
|
381
434
|
},
|
|
382
|
-
children:
|
|
435
|
+
children: normalizedOptions.map((option) => /* @__PURE__ */ jsx7(MenuItem, { value: option.value, disabled: option.disabled, children: renderOption === void 0 ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
436
|
+
option.icon === void 0 ? null : /* @__PURE__ */ jsx7(ListItemIcon, { sx: { minWidth: 32 }, children: option.icon }),
|
|
437
|
+
/* @__PURE__ */ jsx7(ListItemText, { primary: option.label, secondary: option.description })
|
|
438
|
+
] }) : renderOption(option) }, option.value))
|
|
383
439
|
}
|
|
384
440
|
),
|
|
385
441
|
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx7(FormHelperText2, { id: helperId, children: helperText })
|
|
@@ -414,9 +470,11 @@ function createMuiTextAreaAdapter(options) {
|
|
|
414
470
|
rows
|
|
415
471
|
}) {
|
|
416
472
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
473
|
+
const textFieldSlotProps = resolved.muiSlotProps?.textField;
|
|
417
474
|
return /* @__PURE__ */ jsx8(
|
|
418
475
|
TextField,
|
|
419
476
|
{
|
|
477
|
+
...textFieldSlotProps,
|
|
420
478
|
id,
|
|
421
479
|
className,
|
|
422
480
|
name,
|
|
@@ -442,7 +500,7 @@ function createMuiTextAreaAdapter(options) {
|
|
|
442
500
|
placeholder,
|
|
443
501
|
fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
|
|
444
502
|
size: resolved.size,
|
|
445
|
-
variant: resolved.variant,
|
|
503
|
+
variant: textFieldSlotProps?.variant ?? resolved.variant,
|
|
446
504
|
onChange: (event) => onChange(event.currentTarget.value)
|
|
447
505
|
}
|
|
448
506
|
);
|
|
@@ -469,6 +527,7 @@ function createMuiTextInputAdapter(options) {
|
|
|
469
527
|
helperText,
|
|
470
528
|
value,
|
|
471
529
|
onChange,
|
|
530
|
+
onKeyDown,
|
|
472
531
|
placeholder,
|
|
473
532
|
maxLength,
|
|
474
533
|
inputMode,
|
|
@@ -478,9 +537,11 @@ function createMuiTextInputAdapter(options) {
|
|
|
478
537
|
step
|
|
479
538
|
}) {
|
|
480
539
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
540
|
+
const textFieldSlotProps = resolved.muiSlotProps?.textField;
|
|
481
541
|
return /* @__PURE__ */ jsx9(
|
|
482
542
|
TextField2,
|
|
483
543
|
{
|
|
544
|
+
...textFieldSlotProps,
|
|
484
545
|
id,
|
|
485
546
|
className,
|
|
486
547
|
name,
|
|
@@ -509,8 +570,9 @@ function createMuiTextInputAdapter(options) {
|
|
|
509
570
|
placeholder,
|
|
510
571
|
fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
|
|
511
572
|
size: resolved.size,
|
|
512
|
-
variant: resolved.variant,
|
|
513
|
-
onChange: (event) => onChange(event.currentTarget.value)
|
|
573
|
+
variant: textFieldSlotProps?.variant ?? resolved.variant,
|
|
574
|
+
onChange: (event) => onChange(event.currentTarget.value),
|
|
575
|
+
onKeyDown
|
|
514
576
|
}
|
|
515
577
|
);
|
|
516
578
|
};
|
|
@@ -521,12 +583,19 @@ var MuiTextInputAdapter = createMuiTextInputAdapter();
|
|
|
521
583
|
import {
|
|
522
584
|
Add,
|
|
523
585
|
ArrowDownward,
|
|
586
|
+
ArrowDropDown,
|
|
524
587
|
ArrowUpward,
|
|
588
|
+
CheckBox,
|
|
525
589
|
Close,
|
|
526
590
|
Delete,
|
|
527
591
|
DragHandle,
|
|
528
592
|
Edit,
|
|
593
|
+
Numbers,
|
|
594
|
+
RadioButtonChecked,
|
|
529
595
|
Settings,
|
|
596
|
+
Star,
|
|
597
|
+
Subject,
|
|
598
|
+
TextFields,
|
|
530
599
|
Translate
|
|
531
600
|
} from "@mui/icons-material";
|
|
532
601
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
@@ -552,6 +621,26 @@ function muiDefaultIconResolver(actionType) {
|
|
|
552
621
|
return /* @__PURE__ */ jsx10(DragHandle, { fontSize: "small" });
|
|
553
622
|
}
|
|
554
623
|
}
|
|
624
|
+
function muiDefaultFieldTypeIcon(type) {
|
|
625
|
+
switch (type) {
|
|
626
|
+
case "text":
|
|
627
|
+
return /* @__PURE__ */ jsx10(TextFields, { fontSize: "small" });
|
|
628
|
+
case "textarea":
|
|
629
|
+
return /* @__PURE__ */ jsx10(Subject, { fontSize: "small" });
|
|
630
|
+
case "number":
|
|
631
|
+
return /* @__PURE__ */ jsx10(Numbers, { fontSize: "small" });
|
|
632
|
+
case "rating":
|
|
633
|
+
return /* @__PURE__ */ jsx10(Star, { fontSize: "small" });
|
|
634
|
+
case "select":
|
|
635
|
+
return /* @__PURE__ */ jsx10(ArrowDropDown, { fontSize: "small" });
|
|
636
|
+
case "multi-select":
|
|
637
|
+
return /* @__PURE__ */ jsx10(CheckBox, { fontSize: "small" });
|
|
638
|
+
case "checkbox":
|
|
639
|
+
return /* @__PURE__ */ jsx10(CheckBox, { fontSize: "small" });
|
|
640
|
+
case "radio":
|
|
641
|
+
return /* @__PURE__ */ jsx10(RadioButtonChecked, { fontSize: "small" });
|
|
642
|
+
}
|
|
643
|
+
}
|
|
555
644
|
|
|
556
645
|
// src/components.ts
|
|
557
646
|
function isAdapterOptions(value) {
|
|
@@ -568,7 +657,8 @@ function buildMuiBuilderComponents(options) {
|
|
|
568
657
|
Section: createMuiSectionAdapter(options),
|
|
569
658
|
Fieldset: createMuiFieldsetAdapter(options),
|
|
570
659
|
ErrorMessage: createMuiErrorMessageAdapter(options),
|
|
571
|
-
renderIcon: muiDefaultIconResolver
|
|
660
|
+
renderIcon: muiDefaultIconResolver,
|
|
661
|
+
renderFieldTypeIcon: muiDefaultFieldTypeIcon
|
|
572
662
|
};
|
|
573
663
|
}
|
|
574
664
|
var muiBuilderComponents = {
|
|
@@ -581,7 +671,8 @@ var muiBuilderComponents = {
|
|
|
581
671
|
Section: MuiSectionAdapter,
|
|
582
672
|
Fieldset: MuiFieldsetAdapter,
|
|
583
673
|
ErrorMessage: MuiErrorMessageAdapter,
|
|
584
|
-
renderIcon: muiDefaultIconResolver
|
|
674
|
+
renderIcon: muiDefaultIconResolver,
|
|
675
|
+
renderFieldTypeIcon: muiDefaultFieldTypeIcon
|
|
585
676
|
};
|
|
586
677
|
function createMuiBuilderComponents(optionsOrOverrides = {}, customOverrides) {
|
|
587
678
|
const options = isAdapterOptions(optionsOrOverrides) ? optionsOrOverrides : void 0;
|
|
@@ -590,6 +681,7 @@ function createMuiBuilderComponents(optionsOrOverrides = {}, customOverrides) {
|
|
|
590
681
|
}
|
|
591
682
|
|
|
592
683
|
// src/slots/FieldEditor.tsx
|
|
684
|
+
import { DEFAULT_FIELD_TYPE_DEFINITIONS } from "@form-engine-ts/core";
|
|
593
685
|
import { Card, Stack as Stack3, Typography as Typography3 } from "@mui/material";
|
|
594
686
|
|
|
595
687
|
// src/slots/OptionEditor.tsx
|
|
@@ -735,17 +827,8 @@ function createMuiToolbarSlot(options) {
|
|
|
735
827
|
var MuiToolbarSlot = createMuiToolbarSlot();
|
|
736
828
|
|
|
737
829
|
// src/slots/FieldEditor.tsx
|
|
738
|
-
import { Fragment, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
739
|
-
var FIELD_TYPES =
|
|
740
|
-
"text",
|
|
741
|
-
"textarea",
|
|
742
|
-
"number",
|
|
743
|
-
"rating",
|
|
744
|
-
"select",
|
|
745
|
-
"multi-select",
|
|
746
|
-
"checkbox",
|
|
747
|
-
"radio"
|
|
748
|
-
];
|
|
830
|
+
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
831
|
+
var FIELD_TYPES = DEFAULT_FIELD_TYPE_DEFINITIONS.map((definition) => definition.type);
|
|
749
832
|
function isFieldType(value) {
|
|
750
833
|
return FIELD_TYPES.some((type) => type === value);
|
|
751
834
|
}
|
|
@@ -784,7 +867,8 @@ function createMuiFieldEditorSlot(options) {
|
|
|
784
867
|
readOnly,
|
|
785
868
|
actions,
|
|
786
869
|
components,
|
|
787
|
-
translate
|
|
870
|
+
translate,
|
|
871
|
+
slots
|
|
788
872
|
}) {
|
|
789
873
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
790
874
|
const { Button: Button2, Checkbox: Checkbox2, Select: Select2, TextArea, TextInput } = components;
|
|
@@ -795,6 +879,11 @@ function createMuiFieldEditorSlot(options) {
|
|
|
795
879
|
const conditionSource = conditionSources.find((source) => source.id === condition?.questionId);
|
|
796
880
|
const descriptionMode = resolved.fieldEditorOptions?.description ?? "editable";
|
|
797
881
|
const titleErrorId = field.title.trim().length === 0 ? `mui-field-${field.id}-title-error` : void 0;
|
|
882
|
+
const FieldTypeSelect = slots?.fieldTypeSelect;
|
|
883
|
+
const FieldEditorHeader = slots?.fieldEditorHeader;
|
|
884
|
+
const changeFieldType = (nextType) => {
|
|
885
|
+
if (allowedTypes.includes(nextType)) actions.changeFieldType(field.id, nextType);
|
|
886
|
+
};
|
|
798
887
|
return /* @__PURE__ */ jsxs7(
|
|
799
888
|
Card,
|
|
800
889
|
{
|
|
@@ -803,26 +892,28 @@ function createMuiFieldEditorSlot(options) {
|
|
|
803
892
|
variant: "outlined",
|
|
804
893
|
sx: resolved.muiSlotProps?.card?.sx ?? { mb: resolved.dense ? 1 : 2, p: resolved.dense ? 1.5 : 2 },
|
|
805
894
|
children: [
|
|
806
|
-
/* @__PURE__ */
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
895
|
+
FieldEditorHeader === void 0 ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
896
|
+
/* @__PURE__ */ jsx13(
|
|
897
|
+
Toolbar,
|
|
898
|
+
{
|
|
899
|
+
schema,
|
|
900
|
+
translate,
|
|
901
|
+
kind: "field",
|
|
902
|
+
targetId: field.id,
|
|
903
|
+
index,
|
|
904
|
+
total: schema.fields.length,
|
|
905
|
+
title: field.title,
|
|
906
|
+
onMoveUp: () => actions.moveField(field.id, index - 1),
|
|
907
|
+
onMoveDown: () => actions.moveField(field.id, index + 1),
|
|
908
|
+
onRemove: () => actions.removeField(field.id),
|
|
909
|
+
readOnly,
|
|
910
|
+
actions,
|
|
911
|
+
components
|
|
912
|
+
}
|
|
913
|
+
),
|
|
914
|
+
/* @__PURE__ */ jsx13(Typography3, { variant: "subtitle1", fontWeight: "bold", children: field.title })
|
|
915
|
+
] }) : /* @__PURE__ */ jsx13(FieldEditorHeader, { field, index, totalFields: schema.fields.length, actions }),
|
|
824
916
|
/* @__PURE__ */ jsxs7(Stack3, { ...resolved.muiSlotProps?.stack, spacing: resolved.dense ? 1 : 2, children: [
|
|
825
|
-
/* @__PURE__ */ jsx13(Typography3, { variant: "subtitle1", fontWeight: "bold", children: field.title }),
|
|
826
917
|
/* @__PURE__ */ jsxs7(Stack3, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
|
|
827
918
|
/* @__PURE__ */ jsx13(
|
|
828
919
|
TextInput,
|
|
@@ -839,22 +930,37 @@ function createMuiFieldEditorSlot(options) {
|
|
|
839
930
|
onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "title", value)
|
|
840
931
|
}
|
|
841
932
|
),
|
|
842
|
-
/* @__PURE__ */ jsx13(
|
|
933
|
+
FieldTypeSelect === void 0 ? /* @__PURE__ */ jsx13(
|
|
843
934
|
Select2,
|
|
844
935
|
{
|
|
845
936
|
id: `mui-field-${field.id}-type`,
|
|
846
937
|
name: `fields.${field.id}.type`,
|
|
847
938
|
label: translate("builder.type"),
|
|
848
939
|
value: allowedTypes.includes(field.type) ? field.type : "",
|
|
849
|
-
options: FIELD_TYPES.filter((type) => allowedTypes.includes(type)).map((type) =>
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
940
|
+
options: FIELD_TYPES.filter((type) => allowedTypes.includes(type)).map((type) => {
|
|
941
|
+
const definition = DEFAULT_FIELD_TYPE_DEFINITIONS.find((candidate) => candidate.type === type);
|
|
942
|
+
return {
|
|
943
|
+
value: type,
|
|
944
|
+
label: translate(definition?.labelKey ?? `builder.fieldType.${type}`),
|
|
945
|
+
icon: components.renderFieldTypeIcon(type),
|
|
946
|
+
...definition?.category === void 0 ? {} : { kind: definition.category }
|
|
947
|
+
};
|
|
948
|
+
}),
|
|
853
949
|
disabled: readOnly,
|
|
854
950
|
onChange: (value) => {
|
|
855
|
-
if (isFieldType(value))
|
|
951
|
+
if (isFieldType(value)) changeFieldType(value);
|
|
856
952
|
}
|
|
857
953
|
}
|
|
954
|
+
) : /* @__PURE__ */ jsx13(
|
|
955
|
+
FieldTypeSelect,
|
|
956
|
+
{
|
|
957
|
+
currentType: field.type,
|
|
958
|
+
allowedTypes,
|
|
959
|
+
onChangeType: changeFieldType,
|
|
960
|
+
disabled: readOnly,
|
|
961
|
+
readOnly,
|
|
962
|
+
renderIcon: components.renderFieldTypeIcon
|
|
963
|
+
}
|
|
858
964
|
)
|
|
859
965
|
] }),
|
|
860
966
|
descriptionMode === "hidden" ? null : /* @__PURE__ */ jsx13(
|
|
@@ -937,7 +1043,7 @@ function createMuiFieldEditorSlot(options) {
|
|
|
937
1043
|
)
|
|
938
1044
|
}
|
|
939
1045
|
),
|
|
940
|
-
condition === void 0 ? null : /* @__PURE__ */ jsxs7(
|
|
1046
|
+
condition === void 0 ? null : /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
941
1047
|
/* @__PURE__ */ jsx13(
|
|
942
1048
|
Select2,
|
|
943
1049
|
{
|
|
@@ -1033,10 +1139,32 @@ var MuiFieldEditorSlot = createMuiFieldEditorSlot();
|
|
|
1033
1139
|
|
|
1034
1140
|
// src/slots/Localization.tsx
|
|
1035
1141
|
import { ExpandMore } from "@mui/icons-material";
|
|
1036
|
-
import {
|
|
1037
|
-
|
|
1142
|
+
import {
|
|
1143
|
+
Accordion,
|
|
1144
|
+
AccordionDetails,
|
|
1145
|
+
AccordionSummary,
|
|
1146
|
+
Alert as Alert2,
|
|
1147
|
+
Box as Box3,
|
|
1148
|
+
Chip,
|
|
1149
|
+
Stack as Stack4,
|
|
1150
|
+
Tab,
|
|
1151
|
+
Tabs,
|
|
1152
|
+
Typography as Typography4
|
|
1153
|
+
} from "@mui/material";
|
|
1154
|
+
import { useEffect, useState } from "react";
|
|
1038
1155
|
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1039
1156
|
var DEFAULT_EMPTY_STATE_MESSAGE = "No translation locales have been added yet. Select a language from the dropdown above to add one.";
|
|
1157
|
+
function normalizeLocaleOptions(options, getLocaleLabel) {
|
|
1158
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1159
|
+
const normalized = [];
|
|
1160
|
+
for (const item of options) {
|
|
1161
|
+
const value = typeof item === "string" ? item : item.value;
|
|
1162
|
+
if (value.length === 0 || seen.has(value)) continue;
|
|
1163
|
+
seen.add(value);
|
|
1164
|
+
normalized.push({ value, label: typeof item === "string" ? getLocaleLabel?.(value) ?? value : item.label });
|
|
1165
|
+
}
|
|
1166
|
+
return normalized;
|
|
1167
|
+
}
|
|
1040
1168
|
function createMuiLocalizationSlot(options) {
|
|
1041
1169
|
return function MuiLocalization({
|
|
1042
1170
|
schema,
|
|
@@ -1055,6 +1183,7 @@ function createMuiLocalizationSlot(options) {
|
|
|
1055
1183
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
1056
1184
|
const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
|
|
1057
1185
|
const [newLocale, setNewLocale] = useState("");
|
|
1186
|
+
const [pendingFocusLocale, setPendingFocusLocale] = useState(null);
|
|
1058
1187
|
const locales = Array.from(
|
|
1059
1188
|
new Set((schema.supportedLocales ?? []).filter((locale) => locale !== schema.defaultLocale))
|
|
1060
1189
|
);
|
|
@@ -1063,21 +1192,44 @@ function createMuiLocalizationSlot(options) {
|
|
|
1063
1192
|
...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
|
|
1064
1193
|
...schema.supportedLocales ?? []
|
|
1065
1194
|
]);
|
|
1066
|
-
const
|
|
1195
|
+
const localizationOptions = resolved.localizationOptions ?? {};
|
|
1196
|
+
const availableLocaleSource = localizationOptions.availableLocales;
|
|
1197
|
+
const availableLocaleOptions = availableLocaleSource === void 0 ? policy?.allowedLocales?.map((value) => ({
|
|
1198
|
+
value,
|
|
1199
|
+
label: resolved.getLocaleLabel?.(value) ?? value
|
|
1200
|
+
})) : normalizeLocaleOptions(availableLocaleSource, resolved.getLocaleLabel);
|
|
1201
|
+
const filteredAvailableLocales = availableLocaleOptions?.filter(
|
|
1202
|
+
(locale) => !registeredLocales.has(locale.value) && (policy?.allowedLocales === void 0 || policy.allowedLocales.includes(locale.value))
|
|
1203
|
+
);
|
|
1204
|
+
const hasLocaleSelector = filteredAvailableLocales !== void 0;
|
|
1067
1205
|
const localeLimitReached = policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales;
|
|
1068
1206
|
const normalizedLocale = newLocale.trim();
|
|
1207
|
+
const selectedLocaleAvailable = !hasLocaleSelector || filteredAvailableLocales.some((locale) => locale.value === normalizedLocale);
|
|
1069
1208
|
const localeAllowed = policy?.allowedLocales === void 0 || policy.allowedLocales.includes(normalizedLocale);
|
|
1070
|
-
const canAddLocale = !readOnly && normalizedLocale.length > 0 && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
|
|
1209
|
+
const canAddLocale = !readOnly && normalizedLocale.length > 0 && selectedLocaleAvailable && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
|
|
1071
1210
|
const handleTabChange = (_event, value) => onCurrentLocaleChange(value);
|
|
1072
1211
|
const addLocale = () => {
|
|
1073
1212
|
if (!canAddLocale) return;
|
|
1074
1213
|
const result = actions.addLocale(normalizedLocale);
|
|
1075
1214
|
if (!result.success) return;
|
|
1076
1215
|
onCurrentLocaleChange(normalizedLocale);
|
|
1216
|
+
if (localizationOptions.autoFocusNewTab ?? true) setPendingFocusLocale(normalizedLocale);
|
|
1077
1217
|
setNewLocale("");
|
|
1078
1218
|
};
|
|
1219
|
+
const handleAddKeyDown = (event) => {
|
|
1220
|
+
if (event.key !== "Enter" || !canAddLocale) return;
|
|
1221
|
+
event.preventDefault();
|
|
1222
|
+
event.stopPropagation();
|
|
1223
|
+
addLocale();
|
|
1224
|
+
};
|
|
1225
|
+
useEffect(() => {
|
|
1226
|
+
if (pendingFocusLocale === null || currentLocale !== pendingFocusLocale) return;
|
|
1227
|
+
const tab = document.getElementById(`mui-builder-locale-tab-${pendingFocusLocale}`);
|
|
1228
|
+
if (tab === null) return;
|
|
1229
|
+
tab.focus();
|
|
1230
|
+
setPendingFocusLocale(null);
|
|
1231
|
+
}, [currentLocale, pendingFocusLocale]);
|
|
1079
1232
|
const stackProps = resolved.muiSlotProps?.stack;
|
|
1080
|
-
const localizationOptions = resolved.localizationOptions ?? {};
|
|
1081
1233
|
const collapsible = localizationOptions.collapsible ?? false;
|
|
1082
1234
|
const defaultLocaleControl = localizationOptions.defaultLocaleControl ?? "editable";
|
|
1083
1235
|
const configuredTranslationLocales = locales.filter((locale) => locale !== schema.defaultLocale);
|
|
@@ -1085,24 +1237,35 @@ function createMuiLocalizationSlot(options) {
|
|
|
1085
1237
|
...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
|
|
1086
1238
|
...configuredTranslationLocales
|
|
1087
1239
|
];
|
|
1088
|
-
const
|
|
1240
|
+
const legacySummaryLabel = configuredTranslationLocales.length === 0 ? "Translations not configured" : `${configuredLocales.length} ${configuredLocales.length === 1 ? "language" : "languages"} configured: ${configuredLocales.map(
|
|
1089
1241
|
(locale) => locale === schema.defaultLocale ? `${resolved.getLocaleLabel?.(locale) ?? locale} (default)` : resolved.getLocaleLabel?.(locale) ?? locale
|
|
1090
1242
|
).join(", ")}`;
|
|
1091
1243
|
const emptyStateMessage = localizationOptions.emptyStateMessage === void 0 ? DEFAULT_EMPTY_STATE_MESSAGE : translate(localizationOptions.emptyStateMessage);
|
|
1244
|
+
const summaryContext = {
|
|
1245
|
+
defaultLocale: schema.defaultLocale ?? "",
|
|
1246
|
+
supportedLocales: schema.supportedLocales ?? [],
|
|
1247
|
+
totalLocales: registeredLocales.size
|
|
1248
|
+
};
|
|
1249
|
+
const summary = localizationOptions.renderSummary === void 0 ? localizationOptions.showSummary ? configuredTranslationLocales.length > 0 ? /* @__PURE__ */ jsx14(Alert2, { severity: "success", sx: { mb: 2 }, children: translate("builder.localization.localesConfiguredSummary", {
|
|
1250
|
+
count: schema.supportedLocales?.length ?? 0
|
|
1251
|
+
}) }) : /* @__PURE__ */ jsx14(Alert2, { severity: "info", sx: { mb: 2 }, children: translate("builder.localization.noLocalesConfigured") }) : null : localizationOptions.renderSummary(summaryContext);
|
|
1092
1252
|
const title = /* @__PURE__ */ jsxs8(Stack4, { alignItems: "center", direction: "row", spacing: 1, children: [
|
|
1093
1253
|
/* @__PURE__ */ jsx14(Typography4, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }),
|
|
1094
|
-
localizationOptions.showSummary ? /* @__PURE__ */ jsx14(
|
|
1254
|
+
localizationOptions.renderSummary === void 0 && localizationOptions.showSummary && configuredTranslationLocales.length > 0 ? /* @__PURE__ */ jsx14(
|
|
1095
1255
|
Chip,
|
|
1096
1256
|
{
|
|
1097
|
-
label:
|
|
1257
|
+
label: legacySummaryLabel,
|
|
1098
1258
|
size: "small",
|
|
1099
1259
|
color: configuredTranslationLocales.length > 0 ? "primary" : "default",
|
|
1100
1260
|
variant: "outlined"
|
|
1101
1261
|
}
|
|
1102
1262
|
) : null
|
|
1103
1263
|
] });
|
|
1264
|
+
const noCandidateLocales = hasLocaleSelector && filteredAvailableLocales.length === 0;
|
|
1265
|
+
const candidateHelperText = localeLimitReached ? void 0 : noCandidateLocales ? translate("builder.localization.allLocalesAdded") : void 0;
|
|
1104
1266
|
const content = /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
|
|
1105
1267
|
!collapsible ? title : null,
|
|
1268
|
+
summary,
|
|
1106
1269
|
/* @__PURE__ */ jsxs8(
|
|
1107
1270
|
Stack4,
|
|
1108
1271
|
{
|
|
@@ -1112,7 +1275,7 @@ function createMuiLocalizationSlot(options) {
|
|
|
1112
1275
|
spacing: resolved.dense ? 1 : 2,
|
|
1113
1276
|
sx: { mt: 1 },
|
|
1114
1277
|
children: [
|
|
1115
|
-
defaultLocaleControl === "hidden" ? null : /* @__PURE__ */ jsx14(
|
|
1278
|
+
defaultLocaleControl === "hidden" ? null : /* @__PURE__ */ jsx14(Box3, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, children: defaultLocaleControl === "readOnly" ? /* @__PURE__ */ jsxs8(Stack4, { spacing: 0.5, children: [
|
|
1116
1279
|
/* @__PURE__ */ jsx14(Typography4, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
|
|
1117
1280
|
/* @__PURE__ */ jsx14(
|
|
1118
1281
|
Chip,
|
|
@@ -1134,36 +1297,52 @@ function createMuiLocalizationSlot(options) {
|
|
|
1134
1297
|
}
|
|
1135
1298
|
}
|
|
1136
1299
|
) }),
|
|
1137
|
-
/* @__PURE__ */ jsx14(
|
|
1138
|
-
|
|
1300
|
+
/* @__PURE__ */ jsx14(Box3, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, onKeyDownCapture: handleAddKeyDown, children: hasLocaleSelector ? /* @__PURE__ */ jsx14(
|
|
1301
|
+
Select2,
|
|
1139
1302
|
{
|
|
1140
1303
|
id: "mui-builder-new-locale",
|
|
1141
|
-
label: translate("builder.
|
|
1304
|
+
label: translate("builder.localization.selectLocaleToAdd"),
|
|
1142
1305
|
value: newLocale,
|
|
1143
|
-
|
|
1306
|
+
options: filteredAvailableLocales.map((locale) => ({ value: locale.value, label: locale.label })),
|
|
1307
|
+
...candidateHelperText === void 0 ? {} : { helperText: candidateHelperText },
|
|
1308
|
+
disabled: readOnly || localeLimitReached || noCandidateLocales,
|
|
1144
1309
|
onChange: setNewLocale
|
|
1145
1310
|
}
|
|
1146
1311
|
) : /* @__PURE__ */ jsx14(
|
|
1147
|
-
|
|
1312
|
+
TextInput,
|
|
1148
1313
|
{
|
|
1149
1314
|
id: "mui-builder-new-locale",
|
|
1150
1315
|
label: translate("builder.addLocale"),
|
|
1151
1316
|
value: newLocale,
|
|
1152
|
-
|
|
1153
|
-
{ value: "", label: "\u2014" },
|
|
1154
|
-
...availableAllowedLocales.map((locale) => ({
|
|
1155
|
-
value: locale,
|
|
1156
|
-
label: resolved.getLocaleLabel?.(locale) ?? locale
|
|
1157
|
-
}))
|
|
1158
|
-
],
|
|
1159
|
-
disabled: readOnly || localeLimitReached || availableAllowedLocales.length === 0,
|
|
1317
|
+
disabled: readOnly || localeLimitReached,
|
|
1160
1318
|
onChange: setNewLocale
|
|
1161
1319
|
}
|
|
1162
1320
|
) }),
|
|
1163
|
-
/* @__PURE__ */ jsx14(
|
|
1321
|
+
/* @__PURE__ */ jsx14(
|
|
1322
|
+
Box3,
|
|
1323
|
+
{
|
|
1324
|
+
sx: {
|
|
1325
|
+
flexShrink: 0,
|
|
1326
|
+
minWidth: "max-content",
|
|
1327
|
+
...localizationOptions.noWrapActions ?? true ? { whiteSpace: "nowrap" } : {}
|
|
1328
|
+
},
|
|
1329
|
+
children: /* @__PURE__ */ jsx14(
|
|
1330
|
+
Button2,
|
|
1331
|
+
{
|
|
1332
|
+
variant: "primary",
|
|
1333
|
+
action: "addLocale",
|
|
1334
|
+
noWrap: localizationOptions.noWrapActions ?? true,
|
|
1335
|
+
disabled: !canAddLocale,
|
|
1336
|
+
onClick: addLocale,
|
|
1337
|
+
children: translate("builder.addLocale")
|
|
1338
|
+
}
|
|
1339
|
+
)
|
|
1340
|
+
}
|
|
1341
|
+
)
|
|
1164
1342
|
]
|
|
1165
1343
|
}
|
|
1166
1344
|
),
|
|
1345
|
+
localeLimitReached ? /* @__PURE__ */ jsx14(Typography4, { variant: "body2", color: "text.secondary", children: translate("builder.localization.maxLocalesReached", { max: policy?.maxLocales ?? 0 }) }) : null,
|
|
1167
1346
|
locales.length === 0 ? null : /* @__PURE__ */ jsx14(
|
|
1168
1347
|
Tabs,
|
|
1169
1348
|
{
|
|
@@ -1175,6 +1354,7 @@ function createMuiLocalizationSlot(options) {
|
|
|
1175
1354
|
children: locales.map((locale) => /* @__PURE__ */ jsx14(
|
|
1176
1355
|
Tab,
|
|
1177
1356
|
{
|
|
1357
|
+
id: `mui-builder-locale-tab-${locale}`,
|
|
1178
1358
|
value: locale,
|
|
1179
1359
|
label: resolved.getLocaleLabel?.(locale) ?? locale,
|
|
1180
1360
|
disabled: readOnly && locale !== currentLocale,
|
|
@@ -1184,10 +1364,11 @@ function createMuiLocalizationSlot(options) {
|
|
|
1184
1364
|
))
|
|
1185
1365
|
}
|
|
1186
1366
|
),
|
|
1187
|
-
!translationAdapterAvailable ? null : /* @__PURE__ */ jsx14(
|
|
1367
|
+
!translationAdapterAvailable ? null : /* @__PURE__ */ jsx14(Box3, { sx: { minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx14(
|
|
1188
1368
|
Button2,
|
|
1189
1369
|
{
|
|
1190
1370
|
variant: "secondary",
|
|
1371
|
+
noWrap: localizationOptions.noWrapActions ?? true,
|
|
1191
1372
|
disabled: readOnly || !editingLocaleConfigured || isTranslating,
|
|
1192
1373
|
onClick: onAutoTranslate,
|
|
1193
1374
|
children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
|
|
@@ -1236,7 +1417,7 @@ function createMuiLocalizationSlot(options) {
|
|
|
1236
1417
|
] });
|
|
1237
1418
|
}
|
|
1238
1419
|
return /* @__PURE__ */ jsx14(
|
|
1239
|
-
|
|
1420
|
+
Box3,
|
|
1240
1421
|
{
|
|
1241
1422
|
"data-mui-slot": "localization",
|
|
1242
1423
|
sx: {
|
|
@@ -1308,7 +1489,8 @@ function MuiFormBuilder({
|
|
|
1308
1489
|
const contextValue = useMemo(() => ({ options: contextOptions }), [contextOptions]);
|
|
1309
1490
|
const components = useMemo(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
|
|
1310
1491
|
const slots = useMemo(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
|
|
1311
|
-
const
|
|
1492
|
+
const placement = contextOptions.localizationOptions?.placement;
|
|
1493
|
+
const resolvedSectionOrder = sectionOrder ?? (placement === void 0 ? contextOptions.layoutOptions?.sectionOrder : MUI_LOCALIZATION_SECTION_ORDERS[placement]);
|
|
1312
1494
|
return /* @__PURE__ */ jsx15(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx15(
|
|
1313
1495
|
FormBuilder,
|
|
1314
1496
|
{
|
|
@@ -1322,6 +1504,7 @@ function MuiFormBuilder({
|
|
|
1322
1504
|
}
|
|
1323
1505
|
export {
|
|
1324
1506
|
DEFAULT_MUI_SECTION_ORDER,
|
|
1507
|
+
MUI_LOCALIZATION_SECTION_ORDERS,
|
|
1325
1508
|
MuiButtonAdapter,
|
|
1326
1509
|
MuiCheckboxAdapter,
|
|
1327
1510
|
MuiErrorMessageAdapter,
|
|
@@ -1356,6 +1539,7 @@ export {
|
|
|
1356
1539
|
mergeMuiAdapterOptions,
|
|
1357
1540
|
muiBuilderComponents,
|
|
1358
1541
|
muiBuilderSlots,
|
|
1542
|
+
muiDefaultFieldTypeIcon,
|
|
1359
1543
|
muiDefaultIconResolver,
|
|
1360
1544
|
resolveMuiAdapterOptions,
|
|
1361
1545
|
useResolvedMuiAdapterOptions
|