@form-engine-ts/mui 2.9.5 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/index.cjs +196 -70
- package/dist/index.d.cts +17 -4
- package/dist/index.d.ts +17 -4
- package/dist/index.js +208 -72
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -25,8 +25,15 @@ import { MuiFormBuilder } from "@form-engine-ts/mui";
|
|
|
25
25
|
sectionOrder: ["basicSettings", "completionMessage", "questions", "addQuestion", "localization"]
|
|
26
26
|
}}
|
|
27
27
|
localizationOptions={{
|
|
28
|
+
availableLocales: [
|
|
29
|
+
{ value: "ja", label: "日本語" },
|
|
30
|
+
{ value: "en", label: "English" }
|
|
31
|
+
],
|
|
32
|
+
placement: "afterQuestions",
|
|
28
33
|
collapsible: true,
|
|
29
34
|
defaultExpanded: "when-configured",
|
|
35
|
+
showSummary: true,
|
|
36
|
+
emptyStateMessage: "No translation locales have been added yet.",
|
|
30
37
|
defaultLocaleControl: "readOnly"
|
|
31
38
|
}}
|
|
32
39
|
muiSlotProps={{ card: { sx: { p: 2 } }, accordion: { elevation: 0 } }}
|
|
@@ -54,6 +61,12 @@ slots as it does for the standard builder.
|
|
|
54
61
|
width options. `fieldEditorOptions.description` and `localizationOptions.defaultLocaleControl` independently make those
|
|
55
62
|
controls editable, read-only, or hidden. Set `dense` to reduce section, editor, option, and toolbar spacing.
|
|
56
63
|
`buttonVariants` can override the MUI variant for `primary`, `secondary`, and `danger` actions independently.
|
|
64
|
+
`localizationOptions.availableLocales` supplies display-ready locale candidates independently from the policy; when
|
|
65
|
+
both are present, only candidates allowed by `allowedLocales` are shown. `placement` supports `top`,
|
|
66
|
+
`beforeQuestions`, `afterQuestions`, and `bottom` section presets. `showSummary` renders a status alert, while
|
|
67
|
+
`renderSummary` can provide a custom summary. `emptyStateMessage` customizes the guidance shown before a translation
|
|
68
|
+
locale is added. `defaultExpanded` also accepts `"always"`; `autoFocusNewTab` focuses a newly added locale tab by
|
|
69
|
+
default.
|
|
57
70
|
`layoutOptions`, `localizationOptions`, and `muiSlotProps` are also accepted in `muiOptions` for low-level factories such
|
|
58
71
|
as `createMuiBuilderSlots`; the dedicated `MuiFormBuilder` props take precedence.
|
|
59
72
|
|
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DEFAULT_MUI_SECTION_ORDER: () => DEFAULT_MUI_SECTION_ORDER,
|
|
24
|
+
MUI_LOCALIZATION_SECTION_ORDERS: () => MUI_LOCALIZATION_SECTION_ORDERS,
|
|
24
25
|
MuiButtonAdapter: () => MuiButtonAdapter,
|
|
25
26
|
MuiCheckboxAdapter: () => MuiCheckboxAdapter,
|
|
26
27
|
MuiErrorMessageAdapter: () => MuiErrorMessageAdapter,
|
|
@@ -72,8 +73,15 @@ var DEFAULT_MUI_SECTION_ORDER = [
|
|
|
72
73
|
"basicSettings",
|
|
73
74
|
"questions",
|
|
74
75
|
"addQuestion",
|
|
75
|
-
"localization"
|
|
76
|
+
"localization",
|
|
77
|
+
"completionMessage"
|
|
76
78
|
];
|
|
79
|
+
var MUI_LOCALIZATION_SECTION_ORDERS = {
|
|
80
|
+
top: ["localization", "basicSettings", "completionMessage", "questions", "addQuestion"],
|
|
81
|
+
beforeQuestions: ["basicSettings", "localization", "completionMessage", "questions", "addQuestion"],
|
|
82
|
+
afterQuestions: ["basicSettings", "questions", "addQuestion", "localization", "completionMessage"],
|
|
83
|
+
bottom: ["basicSettings", "completionMessage", "questions", "addQuestion", "localization"]
|
|
84
|
+
};
|
|
77
85
|
function resolveMuiAdapterOptions(options = {}) {
|
|
78
86
|
const buttonVariant = options.buttonVariant ?? "contained";
|
|
79
87
|
return {
|
|
@@ -98,7 +106,14 @@ function resolveMuiAdapterOptions(options = {}) {
|
|
|
98
106
|
localizationOptions: {
|
|
99
107
|
collapsible: options.localizationOptions?.collapsible ?? false,
|
|
100
108
|
defaultExpanded: options.localizationOptions?.defaultExpanded ?? false,
|
|
101
|
-
|
|
109
|
+
showSummary: options.localizationOptions?.showSummary ?? false,
|
|
110
|
+
...options.localizationOptions?.availableLocales === void 0 ? {} : { availableLocales: options.localizationOptions.availableLocales },
|
|
111
|
+
...options.localizationOptions?.placement === void 0 ? {} : { placement: options.localizationOptions.placement },
|
|
112
|
+
...options.localizationOptions?.renderSummary === void 0 ? {} : { renderSummary: options.localizationOptions.renderSummary },
|
|
113
|
+
...options.localizationOptions?.emptyStateMessage === void 0 ? {} : { emptyStateMessage: options.localizationOptions.emptyStateMessage },
|
|
114
|
+
defaultLocaleControl: options.localizationOptions?.defaultLocaleControl ?? "editable",
|
|
115
|
+
noWrapActions: options.localizationOptions?.noWrapActions ?? true,
|
|
116
|
+
autoFocusNewTab: options.localizationOptions?.autoFocusNewTab ?? true
|
|
102
117
|
},
|
|
103
118
|
muiSlotProps: options.muiSlotProps ?? {}
|
|
104
119
|
};
|
|
@@ -136,6 +151,7 @@ function createMuiButtonAdapter(options) {
|
|
|
136
151
|
"aria-describedby": ariaDescribedBy,
|
|
137
152
|
"aria-labelledby": ariaLabelledBy,
|
|
138
153
|
onClick,
|
|
154
|
+
noWrap,
|
|
139
155
|
children,
|
|
140
156
|
title,
|
|
141
157
|
variant,
|
|
@@ -161,6 +177,7 @@ function createMuiButtonAdapter(options) {
|
|
|
161
177
|
color: variant === "danger" ? "error" : "primary",
|
|
162
178
|
variant: resolved.buttonVariants?.[variant ?? "primary"] ?? resolved.buttonVariant,
|
|
163
179
|
fullWidth: resolved.buttonFullWidth ?? false,
|
|
180
|
+
sx: { whiteSpace: noWrap === false ? "normal" : "nowrap" },
|
|
164
181
|
children
|
|
165
182
|
}
|
|
166
183
|
);
|
|
@@ -189,6 +206,8 @@ function createMuiCheckboxAdapter(options) {
|
|
|
189
206
|
label
|
|
190
207
|
}) {
|
|
191
208
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
209
|
+
const helperId = id === void 0 ? void 0 : ariaDescribedBy?.split(/\s+/u)[0] ?? `${id}-helper-text`;
|
|
210
|
+
const describedBy = ariaDescribedBy ?? (helperText === void 0 || helperText.length === 0 ? void 0 : helperId);
|
|
192
211
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_material2.FormControl, { className, error: Boolean(error), required, disabled: disabled || readOnly, children: [
|
|
193
212
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
194
213
|
import_material2.FormControlLabel,
|
|
@@ -205,7 +224,7 @@ function createMuiCheckboxAdapter(options) {
|
|
|
205
224
|
disabled: disabled || readOnly,
|
|
206
225
|
inputProps: {
|
|
207
226
|
"aria-label": ariaLabel,
|
|
208
|
-
"aria-describedby":
|
|
227
|
+
"aria-describedby": describedBy,
|
|
209
228
|
"aria-labelledby": ariaLabelledBy
|
|
210
229
|
},
|
|
211
230
|
onChange: (event) => onChange(event.target.checked)
|
|
@@ -213,7 +232,7 @@ function createMuiCheckboxAdapter(options) {
|
|
|
213
232
|
)
|
|
214
233
|
}
|
|
215
234
|
),
|
|
216
|
-
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_material2.FormHelperText, { id:
|
|
235
|
+
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_material2.FormHelperText, { id: helperId, children: helperText })
|
|
217
236
|
] });
|
|
218
237
|
};
|
|
219
238
|
}
|
|
@@ -402,10 +421,13 @@ function createMuiSelectAdapter(options) {
|
|
|
402
421
|
helperText,
|
|
403
422
|
value,
|
|
404
423
|
onChange,
|
|
424
|
+
onKeyDown,
|
|
405
425
|
options: selectOptions
|
|
406
426
|
}) {
|
|
407
427
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
408
428
|
const labelId = id === void 0 || label === void 0 ? void 0 : `${id}-label`;
|
|
429
|
+
const helperId = id === void 0 ? void 0 : ariaDescribedBy?.split(/\s+/u)[0] ?? `${id}-helper-text`;
|
|
430
|
+
const describedBy = ariaDescribedBy ?? (helperText === void 0 || helperText.length === 0 ? void 0 : helperId);
|
|
409
431
|
const handleChange = (event) => onChange(event.target.value);
|
|
410
432
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
411
433
|
import_material7.FormControl,
|
|
@@ -427,18 +449,20 @@ function createMuiSelectAdapter(options) {
|
|
|
427
449
|
name,
|
|
428
450
|
label,
|
|
429
451
|
value,
|
|
452
|
+
disabled,
|
|
430
453
|
onChange: handleChange,
|
|
454
|
+
onKeyDown,
|
|
431
455
|
required,
|
|
432
456
|
readOnly,
|
|
433
457
|
inputProps: {
|
|
434
458
|
"aria-label": ariaLabel,
|
|
435
|
-
"aria-describedby":
|
|
459
|
+
"aria-describedby": describedBy,
|
|
436
460
|
"aria-labelledby": ariaLabelledBy
|
|
437
461
|
},
|
|
438
462
|
children: selectOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_material7.MenuItem, { value: option.value, disabled: option.disabled, children: option.label }, option.value))
|
|
439
463
|
}
|
|
440
464
|
),
|
|
441
|
-
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_material7.FormHelperText, { id:
|
|
465
|
+
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_material7.FormHelperText, { id: helperId, children: helperText })
|
|
442
466
|
]
|
|
443
467
|
}
|
|
444
468
|
);
|
|
@@ -525,6 +549,7 @@ function createMuiTextInputAdapter(options) {
|
|
|
525
549
|
helperText,
|
|
526
550
|
value,
|
|
527
551
|
onChange,
|
|
552
|
+
onKeyDown,
|
|
528
553
|
placeholder,
|
|
529
554
|
maxLength,
|
|
530
555
|
inputMode,
|
|
@@ -566,7 +591,8 @@ function createMuiTextInputAdapter(options) {
|
|
|
566
591
|
fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
|
|
567
592
|
size: resolved.size,
|
|
568
593
|
variant: resolved.variant,
|
|
569
|
-
onChange: (event) => onChange(event.currentTarget.value)
|
|
594
|
+
onChange: (event) => onChange(event.currentTarget.value),
|
|
595
|
+
onKeyDown
|
|
570
596
|
}
|
|
571
597
|
);
|
|
572
598
|
};
|
|
@@ -1082,6 +1108,18 @@ var import_icons_material2 = require("@mui/icons-material");
|
|
|
1082
1108
|
var import_material13 = require("@mui/material");
|
|
1083
1109
|
var import_react2 = require("react");
|
|
1084
1110
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1111
|
+
var DEFAULT_EMPTY_STATE_MESSAGE = "No translation locales have been added yet. Select a language from the dropdown above to add one.";
|
|
1112
|
+
function normalizeLocaleOptions(options, getLocaleLabel) {
|
|
1113
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1114
|
+
const normalized = [];
|
|
1115
|
+
for (const item of options) {
|
|
1116
|
+
const value = typeof item === "string" ? item : item.value;
|
|
1117
|
+
if (value.length === 0 || seen.has(value)) continue;
|
|
1118
|
+
seen.add(value);
|
|
1119
|
+
normalized.push({ value, label: typeof item === "string" ? getLocaleLabel?.(value) ?? value : item.label });
|
|
1120
|
+
}
|
|
1121
|
+
return normalized;
|
|
1122
|
+
}
|
|
1085
1123
|
function createMuiLocalizationSlot(options) {
|
|
1086
1124
|
return function MuiLocalization({
|
|
1087
1125
|
schema,
|
|
@@ -1100,6 +1138,7 @@ function createMuiLocalizationSlot(options) {
|
|
|
1100
1138
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
1101
1139
|
const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
|
|
1102
1140
|
const [newLocale, setNewLocale] = (0, import_react2.useState)("");
|
|
1141
|
+
const [pendingFocusLocale, setPendingFocusLocale] = (0, import_react2.useState)(null);
|
|
1103
1142
|
const locales = Array.from(
|
|
1104
1143
|
new Set((schema.supportedLocales ?? []).filter((locale) => locale !== schema.defaultLocale))
|
|
1105
1144
|
);
|
|
@@ -1108,75 +1147,157 @@ function createMuiLocalizationSlot(options) {
|
|
|
1108
1147
|
...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
|
|
1109
1148
|
...schema.supportedLocales ?? []
|
|
1110
1149
|
]);
|
|
1111
|
-
const
|
|
1150
|
+
const localizationOptions = resolved.localizationOptions ?? {};
|
|
1151
|
+
const availableLocaleSource = localizationOptions.availableLocales;
|
|
1152
|
+
const availableLocaleOptions = availableLocaleSource === void 0 ? policy?.allowedLocales?.map((value) => ({
|
|
1153
|
+
value,
|
|
1154
|
+
label: resolved.getLocaleLabel?.(value) ?? value
|
|
1155
|
+
})) : normalizeLocaleOptions(availableLocaleSource, resolved.getLocaleLabel);
|
|
1156
|
+
const filteredAvailableLocales = availableLocaleOptions?.filter(
|
|
1157
|
+
(locale) => !registeredLocales.has(locale.value) && (policy?.allowedLocales === void 0 || policy.allowedLocales.includes(locale.value))
|
|
1158
|
+
);
|
|
1159
|
+
const hasLocaleSelector = filteredAvailableLocales !== void 0;
|
|
1112
1160
|
const localeLimitReached = policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales;
|
|
1113
1161
|
const normalizedLocale = newLocale.trim();
|
|
1162
|
+
const selectedLocaleAvailable = !hasLocaleSelector || filteredAvailableLocales.some((locale) => locale.value === normalizedLocale);
|
|
1114
1163
|
const localeAllowed = policy?.allowedLocales === void 0 || policy.allowedLocales.includes(normalizedLocale);
|
|
1115
|
-
const canAddLocale = !readOnly && normalizedLocale.length > 0 && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
|
|
1164
|
+
const canAddLocale = !readOnly && normalizedLocale.length > 0 && selectedLocaleAvailable && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
|
|
1116
1165
|
const handleTabChange = (_event, value) => onCurrentLocaleChange(value);
|
|
1117
1166
|
const addLocale = () => {
|
|
1118
1167
|
if (!canAddLocale) return;
|
|
1119
1168
|
const result = actions.addLocale(normalizedLocale);
|
|
1120
1169
|
if (!result.success) return;
|
|
1121
1170
|
onCurrentLocaleChange(normalizedLocale);
|
|
1171
|
+
if (localizationOptions.autoFocusNewTab ?? true) setPendingFocusLocale(normalizedLocale);
|
|
1122
1172
|
setNewLocale("");
|
|
1123
1173
|
};
|
|
1174
|
+
const handleAddKeyDown = (event) => {
|
|
1175
|
+
if (event.key !== "Enter" || !canAddLocale) return;
|
|
1176
|
+
event.preventDefault();
|
|
1177
|
+
event.stopPropagation();
|
|
1178
|
+
addLocale();
|
|
1179
|
+
};
|
|
1180
|
+
(0, import_react2.useEffect)(() => {
|
|
1181
|
+
if (pendingFocusLocale === null || currentLocale !== pendingFocusLocale) return;
|
|
1182
|
+
const tab = document.getElementById(`mui-builder-locale-tab-${pendingFocusLocale}`);
|
|
1183
|
+
if (tab === null) return;
|
|
1184
|
+
tab.focus();
|
|
1185
|
+
setPendingFocusLocale(null);
|
|
1186
|
+
}, [currentLocale, pendingFocusLocale]);
|
|
1124
1187
|
const stackProps = resolved.muiSlotProps?.stack;
|
|
1125
|
-
const collapsible =
|
|
1126
|
-
const defaultLocaleControl =
|
|
1188
|
+
const collapsible = localizationOptions.collapsible ?? false;
|
|
1189
|
+
const defaultLocaleControl = localizationOptions.defaultLocaleControl ?? "editable";
|
|
1190
|
+
const configuredTranslationLocales = locales.filter((locale) => locale !== schema.defaultLocale);
|
|
1191
|
+
const configuredLocales = [
|
|
1192
|
+
...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
|
|
1193
|
+
...configuredTranslationLocales
|
|
1194
|
+
];
|
|
1195
|
+
const legacySummaryLabel = configuredTranslationLocales.length === 0 ? "Translations not configured" : `${configuredLocales.length} ${configuredLocales.length === 1 ? "language" : "languages"} configured: ${configuredLocales.map(
|
|
1196
|
+
(locale) => locale === schema.defaultLocale ? `${resolved.getLocaleLabel?.(locale) ?? locale} (default)` : resolved.getLocaleLabel?.(locale) ?? locale
|
|
1197
|
+
).join(", ")}`;
|
|
1198
|
+
const emptyStateMessage = localizationOptions.emptyStateMessage === void 0 ? DEFAULT_EMPTY_STATE_MESSAGE : translate(localizationOptions.emptyStateMessage);
|
|
1199
|
+
const summaryContext = {
|
|
1200
|
+
defaultLocale: schema.defaultLocale ?? "",
|
|
1201
|
+
supportedLocales: schema.supportedLocales ?? [],
|
|
1202
|
+
totalLocales: registeredLocales.size
|
|
1203
|
+
};
|
|
1204
|
+
const summary = localizationOptions.renderSummary === void 0 ? localizationOptions.showSummary ? configuredTranslationLocales.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Alert, { severity: "success", sx: { mb: 2 }, children: translate("builder.localization.localesConfiguredSummary", {
|
|
1205
|
+
count: schema.supportedLocales?.length ?? 0
|
|
1206
|
+
}) }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Alert, { severity: "info", sx: { mb: 2 }, children: translate("builder.localization.noLocalesConfigured") }) : null : localizationOptions.renderSummary(summaryContext);
|
|
1207
|
+
const title = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { alignItems: "center", direction: "row", spacing: 1, children: [
|
|
1208
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }),
|
|
1209
|
+
localizationOptions.renderSummary === void 0 && localizationOptions.showSummary && configuredTranslationLocales.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1210
|
+
import_material13.Chip,
|
|
1211
|
+
{
|
|
1212
|
+
label: legacySummaryLabel,
|
|
1213
|
+
size: "small",
|
|
1214
|
+
color: configuredTranslationLocales.length > 0 ? "primary" : "default",
|
|
1215
|
+
variant: "outlined"
|
|
1216
|
+
}
|
|
1217
|
+
) : null
|
|
1218
|
+
] });
|
|
1219
|
+
const noCandidateLocales = hasLocaleSelector && filteredAvailableLocales.length === 0;
|
|
1220
|
+
const candidateHelperText = localeLimitReached ? void 0 : noCandidateLocales ? translate("builder.localization.allLocalesAdded") : void 0;
|
|
1127
1221
|
const content = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
|
|
1128
|
-
!collapsible ?
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1222
|
+
!collapsible ? title : null,
|
|
1223
|
+
summary,
|
|
1224
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1225
|
+
import_material13.Stack,
|
|
1226
|
+
{
|
|
1227
|
+
...stackProps,
|
|
1228
|
+
direction: { xs: "column", sm: "row" },
|
|
1229
|
+
alignItems: { xs: "stretch", sm: "center" },
|
|
1230
|
+
spacing: resolved.dense ? 1 : 2,
|
|
1231
|
+
sx: { mt: 1 },
|
|
1232
|
+
children: [
|
|
1233
|
+
defaultLocaleControl === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Box, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, children: defaultLocaleControl === "readOnly" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { spacing: 0.5, children: [
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
|
|
1235
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1236
|
+
import_material13.Chip,
|
|
1237
|
+
{
|
|
1238
|
+
label: resolved.getLocaleLabel?.(schema.defaultLocale ?? "") ?? schema.defaultLocale ?? "",
|
|
1239
|
+
size: resolved.size
|
|
1240
|
+
}
|
|
1241
|
+
)
|
|
1242
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1243
|
+
TextInput,
|
|
1244
|
+
{
|
|
1245
|
+
id: "mui-builder-default-locale",
|
|
1246
|
+
label: translate("builder.defaultLocale"),
|
|
1247
|
+
value: schema.defaultLocale ?? "",
|
|
1248
|
+
disabled: readOnly,
|
|
1249
|
+
onChange: (value) => {
|
|
1250
|
+
const result = actions.setDefaultLocale(value);
|
|
1251
|
+
if (result.success && value === currentLocale) onCurrentLocaleChange("");
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
) }),
|
|
1255
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Box, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, onKeyDownCapture: handleAddKeyDown, children: hasLocaleSelector ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1256
|
+
Select2,
|
|
1257
|
+
{
|
|
1258
|
+
id: "mui-builder-new-locale",
|
|
1259
|
+
label: translate("builder.localization.selectLocaleToAdd"),
|
|
1260
|
+
value: newLocale,
|
|
1261
|
+
options: filteredAvailableLocales.map((locale) => ({ value: locale.value, label: locale.label })),
|
|
1262
|
+
...candidateHelperText === void 0 ? {} : { helperText: candidateHelperText },
|
|
1263
|
+
disabled: readOnly || localeLimitReached || noCandidateLocales,
|
|
1264
|
+
onChange: setNewLocale
|
|
1265
|
+
}
|
|
1266
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1267
|
+
TextInput,
|
|
1268
|
+
{
|
|
1269
|
+
id: "mui-builder-new-locale",
|
|
1270
|
+
label: translate("builder.addLocale"),
|
|
1271
|
+
value: newLocale,
|
|
1272
|
+
disabled: readOnly || localeLimitReached,
|
|
1273
|
+
onChange: setNewLocale
|
|
1274
|
+
}
|
|
1275
|
+
) }),
|
|
1276
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1277
|
+
import_material13.Box,
|
|
1278
|
+
{
|
|
1279
|
+
sx: {
|
|
1280
|
+
flexShrink: 0,
|
|
1281
|
+
minWidth: "max-content",
|
|
1282
|
+
...localizationOptions.noWrapActions ?? true ? { whiteSpace: "nowrap" } : {}
|
|
1283
|
+
},
|
|
1284
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1285
|
+
Button2,
|
|
1286
|
+
{
|
|
1287
|
+
variant: "primary",
|
|
1288
|
+
action: "addLocale",
|
|
1289
|
+
noWrap: localizationOptions.noWrapActions ?? true,
|
|
1290
|
+
disabled: !canAddLocale,
|
|
1291
|
+
onClick: addLocale,
|
|
1292
|
+
children: translate("builder.addLocale")
|
|
1293
|
+
}
|
|
1294
|
+
)
|
|
1295
|
+
}
|
|
1296
|
+
)
|
|
1297
|
+
]
|
|
1298
|
+
}
|
|
1299
|
+
),
|
|
1300
|
+
localeLimitReached ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "body2", color: "text.secondary", children: translate("builder.localization.maxLocalesReached", { max: policy?.maxLocales ?? 0 }) }) : null,
|
|
1180
1301
|
locales.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1181
1302
|
import_material13.Tabs,
|
|
1182
1303
|
{
|
|
@@ -1188,25 +1309,28 @@ function createMuiLocalizationSlot(options) {
|
|
|
1188
1309
|
children: locales.map((locale) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1189
1310
|
import_material13.Tab,
|
|
1190
1311
|
{
|
|
1312
|
+
id: `mui-builder-locale-tab-${locale}`,
|
|
1191
1313
|
value: locale,
|
|
1192
1314
|
label: resolved.getLocaleLabel?.(locale) ?? locale,
|
|
1193
|
-
disabled: readOnly && locale !== currentLocale
|
|
1315
|
+
disabled: readOnly && locale !== currentLocale,
|
|
1316
|
+
sx: { whiteSpace: "nowrap" }
|
|
1194
1317
|
},
|
|
1195
1318
|
locale
|
|
1196
1319
|
))
|
|
1197
1320
|
}
|
|
1198
1321
|
),
|
|
1199
|
-
!translationAdapterAvailable ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1322
|
+
!translationAdapterAvailable ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Box, { sx: { minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1200
1323
|
Button2,
|
|
1201
1324
|
{
|
|
1202
1325
|
variant: "secondary",
|
|
1326
|
+
noWrap: localizationOptions.noWrapActions ?? true,
|
|
1203
1327
|
disabled: readOnly || !editingLocaleConfigured || isTranslating,
|
|
1204
1328
|
onClick: onAutoTranslate,
|
|
1205
1329
|
children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
|
|
1206
1330
|
}
|
|
1207
|
-
),
|
|
1331
|
+
) }),
|
|
1208
1332
|
translationError === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ErrorMessage, { message: translationError }),
|
|
1209
|
-
!editingLocaleConfigured ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "body2", color: "text.secondary", children: translate("builder.selectLocale") }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
|
|
1333
|
+
!editingLocaleConfigured ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "body2", color: "text.secondary", children: locales.length === 0 ? emptyStateMessage : translate("builder.selectLocale") }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
|
|
1210
1334
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1211
1335
|
TextInput,
|
|
1212
1336
|
{
|
|
@@ -1240,10 +1364,10 @@ function createMuiLocalizationSlot(options) {
|
|
|
1240
1364
|
] })
|
|
1241
1365
|
] });
|
|
1242
1366
|
const configured = locales.length > 0;
|
|
1243
|
-
const defaultExpanded =
|
|
1367
|
+
const defaultExpanded = localizationOptions.defaultExpanded === "when-configured" ? configured : localizationOptions.defaultExpanded === "always" ? true : localizationOptions.defaultExpanded ?? false;
|
|
1244
1368
|
if (collapsible) {
|
|
1245
1369
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Accordion, { ...resolved.muiSlotProps?.accordion, "data-mui-slot": "localization", defaultExpanded, children: [
|
|
1246
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.AccordionSummary, { expandIcon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_material2.ExpandMore, {}), children:
|
|
1370
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.AccordionSummary, { expandIcon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_material2.ExpandMore, {}), children: title }),
|
|
1247
1371
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.AccordionDetails, { children: content })
|
|
1248
1372
|
] });
|
|
1249
1373
|
}
|
|
@@ -1318,7 +1442,8 @@ function MuiFormBuilder({
|
|
|
1318
1442
|
const contextValue = (0, import_react4.useMemo)(() => ({ options: contextOptions }), [contextOptions]);
|
|
1319
1443
|
const components = (0, import_react4.useMemo)(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
|
|
1320
1444
|
const slots = (0, import_react4.useMemo)(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
|
|
1321
|
-
const
|
|
1445
|
+
const placement = contextOptions.localizationOptions?.placement;
|
|
1446
|
+
const resolvedSectionOrder = sectionOrder ?? (placement === void 0 ? contextOptions.layoutOptions?.sectionOrder : MUI_LOCALIZATION_SECTION_ORDERS[placement]);
|
|
1322
1447
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1323
1448
|
import_react3.FormBuilder,
|
|
1324
1449
|
{
|
|
@@ -1333,6 +1458,7 @@ function MuiFormBuilder({
|
|
|
1333
1458
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1334
1459
|
0 && (module.exports = {
|
|
1335
1460
|
DEFAULT_MUI_SECTION_ORDER,
|
|
1461
|
+
MUI_LOCALIZATION_SECTION_ORDERS,
|
|
1336
1462
|
MuiButtonAdapter,
|
|
1337
1463
|
MuiCheckboxAdapter,
|
|
1338
1464
|
MuiErrorMessageAdapter,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
|
-
import { BuilderActionIconType, BuilderButtonProps, BuilderCheckboxProps, BuilderErrorMessageProps, BuilderFieldsetProps, BuilderIconButtonProps, BuilderSectionProps, BuilderSelectProps, BuilderTextAreaProps, BuilderTextInputProps, FormBuilderComponents, FormBuilderSlots, FormBuilderProps, BuilderFieldEditorSlotProps, BuilderLocalizationSlotProps, BuilderOptionEditorSlotProps, BuilderToolbarSlotProps } from '@form-engine-ts/react';
|
|
1
|
+
import { BuilderActionIconType, LocalizationSummaryContext, BuilderButtonProps, BuilderCheckboxProps, BuilderErrorMessageProps, BuilderFieldsetProps, BuilderIconButtonProps, BuilderSectionProps, BuilderSelectProps, BuilderTextAreaProps, BuilderTextInputProps, FormBuilderComponents, FormBuilderSlots, FormBuilderProps, BuilderFieldEditorSlotProps, BuilderLocalizationSlotProps, BuilderOptionEditorSlotProps, BuilderToolbarSlotProps } from '@form-engine-ts/react';
|
|
2
2
|
import * as react from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { ReactNode, ComponentType } from 'react';
|
|
4
4
|
import { CardProps, PaperProps, StackProps, AccordionProps } from '@mui/material';
|
|
5
5
|
|
|
6
6
|
type BuilderSectionName = "basicSettings" | "completionMessage" | "questions" | "addQuestion" | "localization";
|
|
7
7
|
type MuiButtonVariant = "contained" | "outlined" | "text";
|
|
8
|
+
interface LocaleOptionItem {
|
|
9
|
+
readonly value: string;
|
|
10
|
+
readonly label: string;
|
|
11
|
+
}
|
|
12
|
+
type LocalizationSectionPlacement = "top" | "beforeQuestions" | "afterQuestions" | "bottom";
|
|
8
13
|
interface MuiLayoutOptions {
|
|
9
14
|
readonly sectionOrder?: readonly BuilderSectionName[];
|
|
10
15
|
}
|
|
11
16
|
interface MuiLocalizationOptions {
|
|
17
|
+
readonly availableLocales?: readonly (LocaleOptionItem | string)[];
|
|
18
|
+
readonly placement?: LocalizationSectionPlacement;
|
|
12
19
|
readonly collapsible?: boolean;
|
|
13
|
-
readonly defaultExpanded?: boolean | "when-configured";
|
|
20
|
+
readonly defaultExpanded?: boolean | "when-configured" | "always";
|
|
21
|
+
readonly showSummary?: boolean;
|
|
22
|
+
readonly renderSummary?: (context: LocalizationSummaryContext) => ReactNode;
|
|
23
|
+
readonly emptyStateMessage?: string;
|
|
14
24
|
readonly defaultLocaleControl?: "editable" | "readOnly" | "hidden";
|
|
25
|
+
readonly noWrapActions?: boolean;
|
|
26
|
+
readonly autoFocusNewTab?: boolean;
|
|
15
27
|
}
|
|
16
28
|
interface MuiFieldEditorOptions {
|
|
17
29
|
readonly description?: "editable" | "readOnly" | "hidden";
|
|
@@ -63,6 +75,7 @@ interface ResolvedMuiAdapterOptions {
|
|
|
63
75
|
readonly muiSlotProps?: MuiBuilderSlotProps;
|
|
64
76
|
}
|
|
65
77
|
declare const DEFAULT_MUI_SECTION_ORDER: readonly BuilderSectionName[];
|
|
78
|
+
declare const MUI_LOCALIZATION_SECTION_ORDERS: Readonly<Record<LocalizationSectionPlacement, readonly BuilderSectionName[]>>;
|
|
66
79
|
declare function resolveMuiAdapterOptions(options?: MuiAdapterOptions): ResolvedMuiAdapterOptions;
|
|
67
80
|
|
|
68
81
|
declare function createMuiButtonAdapter(options?: MuiAdapterOptions): ComponentType<BuilderButtonProps>;
|
|
@@ -136,4 +149,4 @@ declare const MuiToolbarSlot: NonNullable<FormBuilderSlots["toolbar"]>;
|
|
|
136
149
|
declare const muiBuilderSlots: FormBuilderSlots;
|
|
137
150
|
declare function createMuiBuilderSlots(options?: MuiAdapterOptions, customOverrides?: Partial<FormBuilderSlots>): FormBuilderSlots;
|
|
138
151
|
|
|
139
|
-
export { type BuilderSectionName, DEFAULT_MUI_SECTION_ORDER, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiErrorMessageAdapter, type MuiFieldEditorOptions, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, MuiFormBuilderContext, type MuiFormBuilderContextValue, type MuiFormBuilderProps, MuiIconButtonAdapter, type MuiLayoutOptions, type MuiLocalizationOptions, MuiLocalizationSlot, MuiOptionEditorSlot, MuiSectionAdapter, MuiSelectAdapter, MuiTextAreaAdapter, MuiTextInputAdapter, MuiToolbarSlot, type ResolvedMuiAdapterOptions, createMuiBuilderComponents, createMuiBuilderProps, createMuiBuilderSlots, createMuiButtonAdapter, createMuiCheckboxAdapter, createMuiErrorMessageAdapter, createMuiFieldEditorSlot, createMuiFieldsetAdapter, createMuiIconButtonAdapter, createMuiLocalizationSlot, createMuiOptionEditorSlot, createMuiSectionAdapter, createMuiSelectAdapter, createMuiTextAreaAdapter, createMuiTextInputAdapter, createMuiToolbarSlot, mergeMuiAdapterOptions, muiBuilderComponents, muiBuilderSlots, muiDefaultIconResolver, resolveMuiAdapterOptions, useResolvedMuiAdapterOptions };
|
|
152
|
+
export { type BuilderSectionName, DEFAULT_MUI_SECTION_ORDER, type LocaleOptionItem, type LocalizationSectionPlacement, MUI_LOCALIZATION_SECTION_ORDERS, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiErrorMessageAdapter, type MuiFieldEditorOptions, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, MuiFormBuilderContext, type MuiFormBuilderContextValue, type MuiFormBuilderProps, MuiIconButtonAdapter, type MuiLayoutOptions, type MuiLocalizationOptions, MuiLocalizationSlot, MuiOptionEditorSlot, MuiSectionAdapter, MuiSelectAdapter, MuiTextAreaAdapter, MuiTextInputAdapter, MuiToolbarSlot, type ResolvedMuiAdapterOptions, createMuiBuilderComponents, createMuiBuilderProps, createMuiBuilderSlots, createMuiButtonAdapter, createMuiCheckboxAdapter, createMuiErrorMessageAdapter, createMuiFieldEditorSlot, createMuiFieldsetAdapter, createMuiIconButtonAdapter, createMuiLocalizationSlot, createMuiOptionEditorSlot, createMuiSectionAdapter, createMuiSelectAdapter, createMuiTextAreaAdapter, createMuiTextInputAdapter, createMuiToolbarSlot, mergeMuiAdapterOptions, muiBuilderComponents, muiBuilderSlots, muiDefaultIconResolver, resolveMuiAdapterOptions, useResolvedMuiAdapterOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
|
-
import { BuilderActionIconType, BuilderButtonProps, BuilderCheckboxProps, BuilderErrorMessageProps, BuilderFieldsetProps, BuilderIconButtonProps, BuilderSectionProps, BuilderSelectProps, BuilderTextAreaProps, BuilderTextInputProps, FormBuilderComponents, FormBuilderSlots, FormBuilderProps, BuilderFieldEditorSlotProps, BuilderLocalizationSlotProps, BuilderOptionEditorSlotProps, BuilderToolbarSlotProps } from '@form-engine-ts/react';
|
|
1
|
+
import { BuilderActionIconType, LocalizationSummaryContext, BuilderButtonProps, BuilderCheckboxProps, BuilderErrorMessageProps, BuilderFieldsetProps, BuilderIconButtonProps, BuilderSectionProps, BuilderSelectProps, BuilderTextAreaProps, BuilderTextInputProps, FormBuilderComponents, FormBuilderSlots, FormBuilderProps, BuilderFieldEditorSlotProps, BuilderLocalizationSlotProps, BuilderOptionEditorSlotProps, BuilderToolbarSlotProps } from '@form-engine-ts/react';
|
|
2
2
|
import * as react from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { ReactNode, ComponentType } from 'react';
|
|
4
4
|
import { CardProps, PaperProps, StackProps, AccordionProps } from '@mui/material';
|
|
5
5
|
|
|
6
6
|
type BuilderSectionName = "basicSettings" | "completionMessage" | "questions" | "addQuestion" | "localization";
|
|
7
7
|
type MuiButtonVariant = "contained" | "outlined" | "text";
|
|
8
|
+
interface LocaleOptionItem {
|
|
9
|
+
readonly value: string;
|
|
10
|
+
readonly label: string;
|
|
11
|
+
}
|
|
12
|
+
type LocalizationSectionPlacement = "top" | "beforeQuestions" | "afterQuestions" | "bottom";
|
|
8
13
|
interface MuiLayoutOptions {
|
|
9
14
|
readonly sectionOrder?: readonly BuilderSectionName[];
|
|
10
15
|
}
|
|
11
16
|
interface MuiLocalizationOptions {
|
|
17
|
+
readonly availableLocales?: readonly (LocaleOptionItem | string)[];
|
|
18
|
+
readonly placement?: LocalizationSectionPlacement;
|
|
12
19
|
readonly collapsible?: boolean;
|
|
13
|
-
readonly defaultExpanded?: boolean | "when-configured";
|
|
20
|
+
readonly defaultExpanded?: boolean | "when-configured" | "always";
|
|
21
|
+
readonly showSummary?: boolean;
|
|
22
|
+
readonly renderSummary?: (context: LocalizationSummaryContext) => ReactNode;
|
|
23
|
+
readonly emptyStateMessage?: string;
|
|
14
24
|
readonly defaultLocaleControl?: "editable" | "readOnly" | "hidden";
|
|
25
|
+
readonly noWrapActions?: boolean;
|
|
26
|
+
readonly autoFocusNewTab?: boolean;
|
|
15
27
|
}
|
|
16
28
|
interface MuiFieldEditorOptions {
|
|
17
29
|
readonly description?: "editable" | "readOnly" | "hidden";
|
|
@@ -63,6 +75,7 @@ interface ResolvedMuiAdapterOptions {
|
|
|
63
75
|
readonly muiSlotProps?: MuiBuilderSlotProps;
|
|
64
76
|
}
|
|
65
77
|
declare const DEFAULT_MUI_SECTION_ORDER: readonly BuilderSectionName[];
|
|
78
|
+
declare const MUI_LOCALIZATION_SECTION_ORDERS: Readonly<Record<LocalizationSectionPlacement, readonly BuilderSectionName[]>>;
|
|
66
79
|
declare function resolveMuiAdapterOptions(options?: MuiAdapterOptions): ResolvedMuiAdapterOptions;
|
|
67
80
|
|
|
68
81
|
declare function createMuiButtonAdapter(options?: MuiAdapterOptions): ComponentType<BuilderButtonProps>;
|
|
@@ -136,4 +149,4 @@ declare const MuiToolbarSlot: NonNullable<FormBuilderSlots["toolbar"]>;
|
|
|
136
149
|
declare const muiBuilderSlots: FormBuilderSlots;
|
|
137
150
|
declare function createMuiBuilderSlots(options?: MuiAdapterOptions, customOverrides?: Partial<FormBuilderSlots>): FormBuilderSlots;
|
|
138
151
|
|
|
139
|
-
export { type BuilderSectionName, DEFAULT_MUI_SECTION_ORDER, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiErrorMessageAdapter, type MuiFieldEditorOptions, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, MuiFormBuilderContext, type MuiFormBuilderContextValue, type MuiFormBuilderProps, MuiIconButtonAdapter, type MuiLayoutOptions, type MuiLocalizationOptions, MuiLocalizationSlot, MuiOptionEditorSlot, MuiSectionAdapter, MuiSelectAdapter, MuiTextAreaAdapter, MuiTextInputAdapter, MuiToolbarSlot, type ResolvedMuiAdapterOptions, createMuiBuilderComponents, createMuiBuilderProps, createMuiBuilderSlots, createMuiButtonAdapter, createMuiCheckboxAdapter, createMuiErrorMessageAdapter, createMuiFieldEditorSlot, createMuiFieldsetAdapter, createMuiIconButtonAdapter, createMuiLocalizationSlot, createMuiOptionEditorSlot, createMuiSectionAdapter, createMuiSelectAdapter, createMuiTextAreaAdapter, createMuiTextInputAdapter, createMuiToolbarSlot, mergeMuiAdapterOptions, muiBuilderComponents, muiBuilderSlots, muiDefaultIconResolver, resolveMuiAdapterOptions, useResolvedMuiAdapterOptions };
|
|
152
|
+
export { type BuilderSectionName, DEFAULT_MUI_SECTION_ORDER, type LocaleOptionItem, type LocalizationSectionPlacement, MUI_LOCALIZATION_SECTION_ORDERS, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiErrorMessageAdapter, type MuiFieldEditorOptions, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, MuiFormBuilderContext, type MuiFormBuilderContextValue, type MuiFormBuilderProps, MuiIconButtonAdapter, type MuiLayoutOptions, type MuiLocalizationOptions, MuiLocalizationSlot, MuiOptionEditorSlot, MuiSectionAdapter, MuiSelectAdapter, MuiTextAreaAdapter, MuiTextInputAdapter, MuiToolbarSlot, type ResolvedMuiAdapterOptions, createMuiBuilderComponents, createMuiBuilderProps, createMuiBuilderSlots, createMuiButtonAdapter, createMuiCheckboxAdapter, createMuiErrorMessageAdapter, createMuiFieldEditorSlot, createMuiFieldsetAdapter, createMuiIconButtonAdapter, createMuiLocalizationSlot, createMuiOptionEditorSlot, createMuiSectionAdapter, createMuiSelectAdapter, createMuiTextAreaAdapter, createMuiTextInputAdapter, createMuiToolbarSlot, mergeMuiAdapterOptions, muiBuilderComponents, muiBuilderSlots, muiDefaultIconResolver, resolveMuiAdapterOptions, useResolvedMuiAdapterOptions };
|
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 {
|
|
@@ -35,7 +42,14 @@ function resolveMuiAdapterOptions(options = {}) {
|
|
|
35
42
|
localizationOptions: {
|
|
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 },
|
|
49
|
+
...options.localizationOptions?.emptyStateMessage === void 0 ? {} : { emptyStateMessage: options.localizationOptions.emptyStateMessage },
|
|
50
|
+
defaultLocaleControl: options.localizationOptions?.defaultLocaleControl ?? "editable",
|
|
51
|
+
noWrapActions: options.localizationOptions?.noWrapActions ?? true,
|
|
52
|
+
autoFocusNewTab: options.localizationOptions?.autoFocusNewTab ?? true
|
|
39
53
|
},
|
|
40
54
|
muiSlotProps: options.muiSlotProps ?? {}
|
|
41
55
|
};
|
|
@@ -73,6 +87,7 @@ function createMuiButtonAdapter(options) {
|
|
|
73
87
|
"aria-describedby": ariaDescribedBy,
|
|
74
88
|
"aria-labelledby": ariaLabelledBy,
|
|
75
89
|
onClick,
|
|
90
|
+
noWrap,
|
|
76
91
|
children,
|
|
77
92
|
title,
|
|
78
93
|
variant,
|
|
@@ -98,6 +113,7 @@ function createMuiButtonAdapter(options) {
|
|
|
98
113
|
color: variant === "danger" ? "error" : "primary",
|
|
99
114
|
variant: resolved.buttonVariants?.[variant ?? "primary"] ?? resolved.buttonVariant,
|
|
100
115
|
fullWidth: resolved.buttonFullWidth ?? false,
|
|
116
|
+
sx: { whiteSpace: noWrap === false ? "normal" : "nowrap" },
|
|
101
117
|
children
|
|
102
118
|
}
|
|
103
119
|
);
|
|
@@ -126,6 +142,8 @@ function createMuiCheckboxAdapter(options) {
|
|
|
126
142
|
label
|
|
127
143
|
}) {
|
|
128
144
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
145
|
+
const helperId = id === void 0 ? void 0 : ariaDescribedBy?.split(/\s+/u)[0] ?? `${id}-helper-text`;
|
|
146
|
+
const describedBy = ariaDescribedBy ?? (helperText === void 0 || helperText.length === 0 ? void 0 : helperId);
|
|
129
147
|
return /* @__PURE__ */ jsxs(FormControl, { className, error: Boolean(error), required, disabled: disabled || readOnly, children: [
|
|
130
148
|
/* @__PURE__ */ jsx2(
|
|
131
149
|
FormControlLabel,
|
|
@@ -142,7 +160,7 @@ function createMuiCheckboxAdapter(options) {
|
|
|
142
160
|
disabled: disabled || readOnly,
|
|
143
161
|
inputProps: {
|
|
144
162
|
"aria-label": ariaLabel,
|
|
145
|
-
"aria-describedby":
|
|
163
|
+
"aria-describedby": describedBy,
|
|
146
164
|
"aria-labelledby": ariaLabelledBy
|
|
147
165
|
},
|
|
148
166
|
onChange: (event) => onChange(event.target.checked)
|
|
@@ -150,7 +168,7 @@ function createMuiCheckboxAdapter(options) {
|
|
|
150
168
|
)
|
|
151
169
|
}
|
|
152
170
|
),
|
|
153
|
-
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx2(FormHelperText, { id:
|
|
171
|
+
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx2(FormHelperText, { id: helperId, children: helperText })
|
|
154
172
|
] });
|
|
155
173
|
};
|
|
156
174
|
}
|
|
@@ -339,10 +357,13 @@ function createMuiSelectAdapter(options) {
|
|
|
339
357
|
helperText,
|
|
340
358
|
value,
|
|
341
359
|
onChange,
|
|
360
|
+
onKeyDown,
|
|
342
361
|
options: selectOptions
|
|
343
362
|
}) {
|
|
344
363
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
345
364
|
const labelId = id === void 0 || label === void 0 ? void 0 : `${id}-label`;
|
|
365
|
+
const helperId = id === void 0 ? void 0 : ariaDescribedBy?.split(/\s+/u)[0] ?? `${id}-helper-text`;
|
|
366
|
+
const describedBy = ariaDescribedBy ?? (helperText === void 0 || helperText.length === 0 ? void 0 : helperId);
|
|
346
367
|
const handleChange = (event) => onChange(event.target.value);
|
|
347
368
|
return /* @__PURE__ */ jsxs4(
|
|
348
369
|
FormControl2,
|
|
@@ -364,18 +385,20 @@ function createMuiSelectAdapter(options) {
|
|
|
364
385
|
name,
|
|
365
386
|
label,
|
|
366
387
|
value,
|
|
388
|
+
disabled,
|
|
367
389
|
onChange: handleChange,
|
|
390
|
+
onKeyDown,
|
|
368
391
|
required,
|
|
369
392
|
readOnly,
|
|
370
393
|
inputProps: {
|
|
371
394
|
"aria-label": ariaLabel,
|
|
372
|
-
"aria-describedby":
|
|
395
|
+
"aria-describedby": describedBy,
|
|
373
396
|
"aria-labelledby": ariaLabelledBy
|
|
374
397
|
},
|
|
375
398
|
children: selectOptions.map((option) => /* @__PURE__ */ jsx7(MenuItem, { value: option.value, disabled: option.disabled, children: option.label }, option.value))
|
|
376
399
|
}
|
|
377
400
|
),
|
|
378
|
-
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx7(FormHelperText2, { id:
|
|
401
|
+
helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx7(FormHelperText2, { id: helperId, children: helperText })
|
|
379
402
|
]
|
|
380
403
|
}
|
|
381
404
|
);
|
|
@@ -462,6 +485,7 @@ function createMuiTextInputAdapter(options) {
|
|
|
462
485
|
helperText,
|
|
463
486
|
value,
|
|
464
487
|
onChange,
|
|
488
|
+
onKeyDown,
|
|
465
489
|
placeholder,
|
|
466
490
|
maxLength,
|
|
467
491
|
inputMode,
|
|
@@ -503,7 +527,8 @@ function createMuiTextInputAdapter(options) {
|
|
|
503
527
|
fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
|
|
504
528
|
size: resolved.size,
|
|
505
529
|
variant: resolved.variant,
|
|
506
|
-
onChange: (event) => onChange(event.currentTarget.value)
|
|
530
|
+
onChange: (event) => onChange(event.currentTarget.value),
|
|
531
|
+
onKeyDown
|
|
507
532
|
}
|
|
508
533
|
);
|
|
509
534
|
};
|
|
@@ -1026,9 +1051,32 @@ var MuiFieldEditorSlot = createMuiFieldEditorSlot();
|
|
|
1026
1051
|
|
|
1027
1052
|
// src/slots/Localization.tsx
|
|
1028
1053
|
import { ExpandMore } from "@mui/icons-material";
|
|
1029
|
-
import {
|
|
1030
|
-
|
|
1054
|
+
import {
|
|
1055
|
+
Accordion,
|
|
1056
|
+
AccordionDetails,
|
|
1057
|
+
AccordionSummary,
|
|
1058
|
+
Alert as Alert2,
|
|
1059
|
+
Box as Box2,
|
|
1060
|
+
Chip,
|
|
1061
|
+
Stack as Stack4,
|
|
1062
|
+
Tab,
|
|
1063
|
+
Tabs,
|
|
1064
|
+
Typography as Typography4
|
|
1065
|
+
} from "@mui/material";
|
|
1066
|
+
import { useEffect, useState } from "react";
|
|
1031
1067
|
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1068
|
+
var DEFAULT_EMPTY_STATE_MESSAGE = "No translation locales have been added yet. Select a language from the dropdown above to add one.";
|
|
1069
|
+
function normalizeLocaleOptions(options, getLocaleLabel) {
|
|
1070
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1071
|
+
const normalized = [];
|
|
1072
|
+
for (const item of options) {
|
|
1073
|
+
const value = typeof item === "string" ? item : item.value;
|
|
1074
|
+
if (value.length === 0 || seen.has(value)) continue;
|
|
1075
|
+
seen.add(value);
|
|
1076
|
+
normalized.push({ value, label: typeof item === "string" ? getLocaleLabel?.(value) ?? value : item.label });
|
|
1077
|
+
}
|
|
1078
|
+
return normalized;
|
|
1079
|
+
}
|
|
1032
1080
|
function createMuiLocalizationSlot(options) {
|
|
1033
1081
|
return function MuiLocalization({
|
|
1034
1082
|
schema,
|
|
@@ -1047,6 +1095,7 @@ function createMuiLocalizationSlot(options) {
|
|
|
1047
1095
|
const resolved = useResolvedMuiAdapterOptions(options);
|
|
1048
1096
|
const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
|
|
1049
1097
|
const [newLocale, setNewLocale] = useState("");
|
|
1098
|
+
const [pendingFocusLocale, setPendingFocusLocale] = useState(null);
|
|
1050
1099
|
const locales = Array.from(
|
|
1051
1100
|
new Set((schema.supportedLocales ?? []).filter((locale) => locale !== schema.defaultLocale))
|
|
1052
1101
|
);
|
|
@@ -1055,75 +1104,157 @@ function createMuiLocalizationSlot(options) {
|
|
|
1055
1104
|
...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
|
|
1056
1105
|
...schema.supportedLocales ?? []
|
|
1057
1106
|
]);
|
|
1058
|
-
const
|
|
1107
|
+
const localizationOptions = resolved.localizationOptions ?? {};
|
|
1108
|
+
const availableLocaleSource = localizationOptions.availableLocales;
|
|
1109
|
+
const availableLocaleOptions = availableLocaleSource === void 0 ? policy?.allowedLocales?.map((value) => ({
|
|
1110
|
+
value,
|
|
1111
|
+
label: resolved.getLocaleLabel?.(value) ?? value
|
|
1112
|
+
})) : normalizeLocaleOptions(availableLocaleSource, resolved.getLocaleLabel);
|
|
1113
|
+
const filteredAvailableLocales = availableLocaleOptions?.filter(
|
|
1114
|
+
(locale) => !registeredLocales.has(locale.value) && (policy?.allowedLocales === void 0 || policy.allowedLocales.includes(locale.value))
|
|
1115
|
+
);
|
|
1116
|
+
const hasLocaleSelector = filteredAvailableLocales !== void 0;
|
|
1059
1117
|
const localeLimitReached = policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales;
|
|
1060
1118
|
const normalizedLocale = newLocale.trim();
|
|
1119
|
+
const selectedLocaleAvailable = !hasLocaleSelector || filteredAvailableLocales.some((locale) => locale.value === normalizedLocale);
|
|
1061
1120
|
const localeAllowed = policy?.allowedLocales === void 0 || policy.allowedLocales.includes(normalizedLocale);
|
|
1062
|
-
const canAddLocale = !readOnly && normalizedLocale.length > 0 && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
|
|
1121
|
+
const canAddLocale = !readOnly && normalizedLocale.length > 0 && selectedLocaleAvailable && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
|
|
1063
1122
|
const handleTabChange = (_event, value) => onCurrentLocaleChange(value);
|
|
1064
1123
|
const addLocale = () => {
|
|
1065
1124
|
if (!canAddLocale) return;
|
|
1066
1125
|
const result = actions.addLocale(normalizedLocale);
|
|
1067
1126
|
if (!result.success) return;
|
|
1068
1127
|
onCurrentLocaleChange(normalizedLocale);
|
|
1128
|
+
if (localizationOptions.autoFocusNewTab ?? true) setPendingFocusLocale(normalizedLocale);
|
|
1069
1129
|
setNewLocale("");
|
|
1070
1130
|
};
|
|
1131
|
+
const handleAddKeyDown = (event) => {
|
|
1132
|
+
if (event.key !== "Enter" || !canAddLocale) return;
|
|
1133
|
+
event.preventDefault();
|
|
1134
|
+
event.stopPropagation();
|
|
1135
|
+
addLocale();
|
|
1136
|
+
};
|
|
1137
|
+
useEffect(() => {
|
|
1138
|
+
if (pendingFocusLocale === null || currentLocale !== pendingFocusLocale) return;
|
|
1139
|
+
const tab = document.getElementById(`mui-builder-locale-tab-${pendingFocusLocale}`);
|
|
1140
|
+
if (tab === null) return;
|
|
1141
|
+
tab.focus();
|
|
1142
|
+
setPendingFocusLocale(null);
|
|
1143
|
+
}, [currentLocale, pendingFocusLocale]);
|
|
1071
1144
|
const stackProps = resolved.muiSlotProps?.stack;
|
|
1072
|
-
const collapsible =
|
|
1073
|
-
const defaultLocaleControl =
|
|
1145
|
+
const collapsible = localizationOptions.collapsible ?? false;
|
|
1146
|
+
const defaultLocaleControl = localizationOptions.defaultLocaleControl ?? "editable";
|
|
1147
|
+
const configuredTranslationLocales = locales.filter((locale) => locale !== schema.defaultLocale);
|
|
1148
|
+
const configuredLocales = [
|
|
1149
|
+
...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
|
|
1150
|
+
...configuredTranslationLocales
|
|
1151
|
+
];
|
|
1152
|
+
const legacySummaryLabel = configuredTranslationLocales.length === 0 ? "Translations not configured" : `${configuredLocales.length} ${configuredLocales.length === 1 ? "language" : "languages"} configured: ${configuredLocales.map(
|
|
1153
|
+
(locale) => locale === schema.defaultLocale ? `${resolved.getLocaleLabel?.(locale) ?? locale} (default)` : resolved.getLocaleLabel?.(locale) ?? locale
|
|
1154
|
+
).join(", ")}`;
|
|
1155
|
+
const emptyStateMessage = localizationOptions.emptyStateMessage === void 0 ? DEFAULT_EMPTY_STATE_MESSAGE : translate(localizationOptions.emptyStateMessage);
|
|
1156
|
+
const summaryContext = {
|
|
1157
|
+
defaultLocale: schema.defaultLocale ?? "",
|
|
1158
|
+
supportedLocales: schema.supportedLocales ?? [],
|
|
1159
|
+
totalLocales: registeredLocales.size
|
|
1160
|
+
};
|
|
1161
|
+
const summary = localizationOptions.renderSummary === void 0 ? localizationOptions.showSummary ? configuredTranslationLocales.length > 0 ? /* @__PURE__ */ jsx14(Alert2, { severity: "success", sx: { mb: 2 }, children: translate("builder.localization.localesConfiguredSummary", {
|
|
1162
|
+
count: schema.supportedLocales?.length ?? 0
|
|
1163
|
+
}) }) : /* @__PURE__ */ jsx14(Alert2, { severity: "info", sx: { mb: 2 }, children: translate("builder.localization.noLocalesConfigured") }) : null : localizationOptions.renderSummary(summaryContext);
|
|
1164
|
+
const title = /* @__PURE__ */ jsxs8(Stack4, { alignItems: "center", direction: "row", spacing: 1, children: [
|
|
1165
|
+
/* @__PURE__ */ jsx14(Typography4, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }),
|
|
1166
|
+
localizationOptions.renderSummary === void 0 && localizationOptions.showSummary && configuredTranslationLocales.length > 0 ? /* @__PURE__ */ jsx14(
|
|
1167
|
+
Chip,
|
|
1168
|
+
{
|
|
1169
|
+
label: legacySummaryLabel,
|
|
1170
|
+
size: "small",
|
|
1171
|
+
color: configuredTranslationLocales.length > 0 ? "primary" : "default",
|
|
1172
|
+
variant: "outlined"
|
|
1173
|
+
}
|
|
1174
|
+
) : null
|
|
1175
|
+
] });
|
|
1176
|
+
const noCandidateLocales = hasLocaleSelector && filteredAvailableLocales.length === 0;
|
|
1177
|
+
const candidateHelperText = localeLimitReached ? void 0 : noCandidateLocales ? translate("builder.localization.allLocalesAdded") : void 0;
|
|
1074
1178
|
const content = /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
|
|
1075
|
-
!collapsible ?
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1179
|
+
!collapsible ? title : null,
|
|
1180
|
+
summary,
|
|
1181
|
+
/* @__PURE__ */ jsxs8(
|
|
1182
|
+
Stack4,
|
|
1183
|
+
{
|
|
1184
|
+
...stackProps,
|
|
1185
|
+
direction: { xs: "column", sm: "row" },
|
|
1186
|
+
alignItems: { xs: "stretch", sm: "center" },
|
|
1187
|
+
spacing: resolved.dense ? 1 : 2,
|
|
1188
|
+
sx: { mt: 1 },
|
|
1189
|
+
children: [
|
|
1190
|
+
defaultLocaleControl === "hidden" ? null : /* @__PURE__ */ jsx14(Box2, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, children: defaultLocaleControl === "readOnly" ? /* @__PURE__ */ jsxs8(Stack4, { spacing: 0.5, children: [
|
|
1191
|
+
/* @__PURE__ */ jsx14(Typography4, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
|
|
1192
|
+
/* @__PURE__ */ jsx14(
|
|
1193
|
+
Chip,
|
|
1194
|
+
{
|
|
1195
|
+
label: resolved.getLocaleLabel?.(schema.defaultLocale ?? "") ?? schema.defaultLocale ?? "",
|
|
1196
|
+
size: resolved.size
|
|
1197
|
+
}
|
|
1198
|
+
)
|
|
1199
|
+
] }) : /* @__PURE__ */ jsx14(
|
|
1200
|
+
TextInput,
|
|
1201
|
+
{
|
|
1202
|
+
id: "mui-builder-default-locale",
|
|
1203
|
+
label: translate("builder.defaultLocale"),
|
|
1204
|
+
value: schema.defaultLocale ?? "",
|
|
1205
|
+
disabled: readOnly,
|
|
1206
|
+
onChange: (value) => {
|
|
1207
|
+
const result = actions.setDefaultLocale(value);
|
|
1208
|
+
if (result.success && value === currentLocale) onCurrentLocaleChange("");
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
) }),
|
|
1212
|
+
/* @__PURE__ */ jsx14(Box2, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, onKeyDownCapture: handleAddKeyDown, children: hasLocaleSelector ? /* @__PURE__ */ jsx14(
|
|
1213
|
+
Select2,
|
|
1214
|
+
{
|
|
1215
|
+
id: "mui-builder-new-locale",
|
|
1216
|
+
label: translate("builder.localization.selectLocaleToAdd"),
|
|
1217
|
+
value: newLocale,
|
|
1218
|
+
options: filteredAvailableLocales.map((locale) => ({ value: locale.value, label: locale.label })),
|
|
1219
|
+
...candidateHelperText === void 0 ? {} : { helperText: candidateHelperText },
|
|
1220
|
+
disabled: readOnly || localeLimitReached || noCandidateLocales,
|
|
1221
|
+
onChange: setNewLocale
|
|
1222
|
+
}
|
|
1223
|
+
) : /* @__PURE__ */ jsx14(
|
|
1224
|
+
TextInput,
|
|
1225
|
+
{
|
|
1226
|
+
id: "mui-builder-new-locale",
|
|
1227
|
+
label: translate("builder.addLocale"),
|
|
1228
|
+
value: newLocale,
|
|
1229
|
+
disabled: readOnly || localeLimitReached,
|
|
1230
|
+
onChange: setNewLocale
|
|
1231
|
+
}
|
|
1232
|
+
) }),
|
|
1233
|
+
/* @__PURE__ */ jsx14(
|
|
1234
|
+
Box2,
|
|
1235
|
+
{
|
|
1236
|
+
sx: {
|
|
1237
|
+
flexShrink: 0,
|
|
1238
|
+
minWidth: "max-content",
|
|
1239
|
+
...localizationOptions.noWrapActions ?? true ? { whiteSpace: "nowrap" } : {}
|
|
1240
|
+
},
|
|
1241
|
+
children: /* @__PURE__ */ jsx14(
|
|
1242
|
+
Button2,
|
|
1243
|
+
{
|
|
1244
|
+
variant: "primary",
|
|
1245
|
+
action: "addLocale",
|
|
1246
|
+
noWrap: localizationOptions.noWrapActions ?? true,
|
|
1247
|
+
disabled: !canAddLocale,
|
|
1248
|
+
onClick: addLocale,
|
|
1249
|
+
children: translate("builder.addLocale")
|
|
1250
|
+
}
|
|
1251
|
+
)
|
|
1252
|
+
}
|
|
1253
|
+
)
|
|
1254
|
+
]
|
|
1255
|
+
}
|
|
1256
|
+
),
|
|
1257
|
+
localeLimitReached ? /* @__PURE__ */ jsx14(Typography4, { variant: "body2", color: "text.secondary", children: translate("builder.localization.maxLocalesReached", { max: policy?.maxLocales ?? 0 }) }) : null,
|
|
1127
1258
|
locales.length === 0 ? null : /* @__PURE__ */ jsx14(
|
|
1128
1259
|
Tabs,
|
|
1129
1260
|
{
|
|
@@ -1135,25 +1266,28 @@ function createMuiLocalizationSlot(options) {
|
|
|
1135
1266
|
children: locales.map((locale) => /* @__PURE__ */ jsx14(
|
|
1136
1267
|
Tab,
|
|
1137
1268
|
{
|
|
1269
|
+
id: `mui-builder-locale-tab-${locale}`,
|
|
1138
1270
|
value: locale,
|
|
1139
1271
|
label: resolved.getLocaleLabel?.(locale) ?? locale,
|
|
1140
|
-
disabled: readOnly && locale !== currentLocale
|
|
1272
|
+
disabled: readOnly && locale !== currentLocale,
|
|
1273
|
+
sx: { whiteSpace: "nowrap" }
|
|
1141
1274
|
},
|
|
1142
1275
|
locale
|
|
1143
1276
|
))
|
|
1144
1277
|
}
|
|
1145
1278
|
),
|
|
1146
|
-
!translationAdapterAvailable ? null : /* @__PURE__ */ jsx14(
|
|
1279
|
+
!translationAdapterAvailable ? null : /* @__PURE__ */ jsx14(Box2, { sx: { minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx14(
|
|
1147
1280
|
Button2,
|
|
1148
1281
|
{
|
|
1149
1282
|
variant: "secondary",
|
|
1283
|
+
noWrap: localizationOptions.noWrapActions ?? true,
|
|
1150
1284
|
disabled: readOnly || !editingLocaleConfigured || isTranslating,
|
|
1151
1285
|
onClick: onAutoTranslate,
|
|
1152
1286
|
children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
|
|
1153
1287
|
}
|
|
1154
|
-
),
|
|
1288
|
+
) }),
|
|
1155
1289
|
translationError === void 0 ? null : /* @__PURE__ */ jsx14(ErrorMessage, { message: translationError }),
|
|
1156
|
-
!editingLocaleConfigured ? /* @__PURE__ */ jsx14(Typography4, { variant: "body2", color: "text.secondary", children: translate("builder.selectLocale") }) : /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
|
|
1290
|
+
!editingLocaleConfigured ? /* @__PURE__ */ jsx14(Typography4, { variant: "body2", color: "text.secondary", children: locales.length === 0 ? emptyStateMessage : translate("builder.selectLocale") }) : /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
|
|
1157
1291
|
/* @__PURE__ */ jsx14(
|
|
1158
1292
|
TextInput,
|
|
1159
1293
|
{
|
|
@@ -1187,10 +1321,10 @@ function createMuiLocalizationSlot(options) {
|
|
|
1187
1321
|
] })
|
|
1188
1322
|
] });
|
|
1189
1323
|
const configured = locales.length > 0;
|
|
1190
|
-
const defaultExpanded =
|
|
1324
|
+
const defaultExpanded = localizationOptions.defaultExpanded === "when-configured" ? configured : localizationOptions.defaultExpanded === "always" ? true : localizationOptions.defaultExpanded ?? false;
|
|
1191
1325
|
if (collapsible) {
|
|
1192
1326
|
return /* @__PURE__ */ jsxs8(Accordion, { ...resolved.muiSlotProps?.accordion, "data-mui-slot": "localization", defaultExpanded, children: [
|
|
1193
|
-
/* @__PURE__ */ jsx14(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx14(ExpandMore, {}), children:
|
|
1327
|
+
/* @__PURE__ */ jsx14(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx14(ExpandMore, {}), children: title }),
|
|
1194
1328
|
/* @__PURE__ */ jsx14(AccordionDetails, { children: content })
|
|
1195
1329
|
] });
|
|
1196
1330
|
}
|
|
@@ -1267,7 +1401,8 @@ function MuiFormBuilder({
|
|
|
1267
1401
|
const contextValue = useMemo(() => ({ options: contextOptions }), [contextOptions]);
|
|
1268
1402
|
const components = useMemo(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
|
|
1269
1403
|
const slots = useMemo(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
|
|
1270
|
-
const
|
|
1404
|
+
const placement = contextOptions.localizationOptions?.placement;
|
|
1405
|
+
const resolvedSectionOrder = sectionOrder ?? (placement === void 0 ? contextOptions.layoutOptions?.sectionOrder : MUI_LOCALIZATION_SECTION_ORDERS[placement]);
|
|
1271
1406
|
return /* @__PURE__ */ jsx15(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx15(
|
|
1272
1407
|
FormBuilder,
|
|
1273
1408
|
{
|
|
@@ -1281,6 +1416,7 @@ function MuiFormBuilder({
|
|
|
1281
1416
|
}
|
|
1282
1417
|
export {
|
|
1283
1418
|
DEFAULT_MUI_SECTION_ORDER,
|
|
1419
|
+
MUI_LOCALIZATION_SECTION_ORDERS,
|
|
1284
1420
|
MuiButtonAdapter,
|
|
1285
1421
|
MuiCheckboxAdapter,
|
|
1286
1422
|
MuiErrorMessageAdapter,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@form-engine-ts/mui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@mui/material": "^6.0.0 || ^7.0.0",
|
|
47
47
|
"react": "^18.0.0 || ^19.0.0",
|
|
48
48
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
49
|
-
"@form-engine-ts/core": "
|
|
50
|
-
"@form-engine-ts/react": "
|
|
49
|
+
"@form-engine-ts/core": "3.0.0",
|
|
50
|
+
"@form-engine-ts/react": "3.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@emotion/react": "^11.14.0",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"@types/react-dom": "^19.2.4",
|
|
59
59
|
"react": "^19.2.8",
|
|
60
60
|
"react-dom": "^19.2.8",
|
|
61
|
-
"@form-engine-ts/core": "
|
|
62
|
-
"@form-engine-ts/react": "
|
|
61
|
+
"@form-engine-ts/core": "3.0.0",
|
|
62
|
+
"@form-engine-ts/react": "3.0.0"
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|
|
65
65
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean --external @emotion/react --external @emotion/styled --external @form-engine-ts/core --external @form-engine-ts/react --external @mui/icons-material --external @mui/material --external react --external react-dom",
|