@form-engine-ts/mui 2.9.4 → 2.9.6

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/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  // src/adapters/Button.tsx
2
2
  import { Button } from "@mui/material";
3
3
 
4
+ // src/context.ts
5
+ import { createContext, useContext } from "react";
6
+
4
7
  // src/types.ts
5
8
  var DEFAULT_MUI_SECTION_ORDER = [
6
9
  "basicSettings",
@@ -20,22 +23,49 @@ function resolveMuiAdapterOptions(options = {}) {
20
23
  danger: options.buttonVariants?.danger ?? buttonVariant
21
24
  },
22
25
  fullWidth: options.fullWidth ?? true,
26
+ inputFullWidth: options.inputFullWidth ?? options.fullWidth ?? true,
27
+ buttonFullWidth: options.buttonFullWidth ?? options.fullWidth ?? false,
23
28
  dense: options.dense ?? false,
24
29
  getLocaleLabel: options.getLocaleLabel ?? ((locale) => locale),
25
30
  ...options.getActionLabel === void 0 ? {} : { getActionLabel: options.getActionLabel },
26
31
  layoutOptions: options.layoutOptions ?? {},
32
+ fieldEditorOptions: {
33
+ description: options.fieldEditorOptions?.description ?? "editable"
34
+ },
27
35
  localizationOptions: {
28
36
  collapsible: options.localizationOptions?.collapsible ?? false,
29
- defaultExpanded: options.localizationOptions?.defaultExpanded ?? false
37
+ defaultExpanded: options.localizationOptions?.defaultExpanded ?? false,
38
+ showSummary: options.localizationOptions?.showSummary ?? false,
39
+ ...options.localizationOptions?.emptyStateMessage === void 0 ? {} : { emptyStateMessage: options.localizationOptions.emptyStateMessage },
40
+ defaultLocaleControl: options.localizationOptions?.defaultLocaleControl ?? "editable"
30
41
  },
31
42
  muiSlotProps: options.muiSlotProps ?? {}
32
43
  };
33
44
  }
34
45
 
46
+ // src/context.ts
47
+ var MuiFormBuilderContext = createContext({ options: {} });
48
+ function mergeMuiAdapterOptions(base = {}, overrides = {}) {
49
+ return {
50
+ ...base,
51
+ ...overrides,
52
+ ...base.buttonVariants === void 0 && overrides.buttonVariants === void 0 ? {} : { buttonVariants: { ...base.buttonVariants, ...overrides.buttonVariants } },
53
+ ...base.layoutOptions === void 0 && overrides.layoutOptions === void 0 ? {} : { layoutOptions: { ...base.layoutOptions, ...overrides.layoutOptions } },
54
+ ...base.fieldEditorOptions === void 0 && overrides.fieldEditorOptions === void 0 ? {} : { fieldEditorOptions: { ...base.fieldEditorOptions, ...overrides.fieldEditorOptions } },
55
+ ...base.localizationOptions === void 0 && overrides.localizationOptions === void 0 ? {} : { localizationOptions: { ...base.localizationOptions, ...overrides.localizationOptions } },
56
+ ...base.muiSlotProps === void 0 && overrides.muiSlotProps === void 0 ? {} : { muiSlotProps: { ...base.muiSlotProps, ...overrides.muiSlotProps } }
57
+ };
58
+ }
59
+ function useResolvedMuiAdapterOptions(overrides) {
60
+ const context = useContext(MuiFormBuilderContext);
61
+ return resolveMuiAdapterOptions(
62
+ overrides === void 0 ? context.options : mergeMuiAdapterOptions(context.options, overrides)
63
+ );
64
+ }
65
+
35
66
  // src/adapters/Button.tsx
36
67
  import { jsx } from "react/jsx-runtime";
37
68
  function createMuiButtonAdapter(options) {
38
- const resolved = resolveMuiAdapterOptions(options);
39
69
  return function MuiButton({
40
70
  id,
41
71
  className,
@@ -51,6 +81,7 @@ function createMuiButtonAdapter(options) {
51
81
  action,
52
82
  targetId
53
83
  }) {
84
+ const resolved = useResolvedMuiAdapterOptions(options);
54
85
  return /* @__PURE__ */ jsx(
55
86
  Button,
56
87
  {
@@ -68,7 +99,8 @@ function createMuiButtonAdapter(options) {
68
99
  onClick,
69
100
  color: variant === "danger" ? "error" : "primary",
70
101
  variant: resolved.buttonVariants?.[variant ?? "primary"] ?? resolved.buttonVariant,
71
- fullWidth: resolved.fullWidth,
102
+ fullWidth: resolved.buttonFullWidth ?? false,
103
+ sx: { whiteSpace: "nowrap" },
72
104
  children
73
105
  }
74
106
  );
@@ -80,7 +112,6 @@ var MuiButtonAdapter = createMuiButtonAdapter();
80
112
  import { Checkbox, FormControl, FormControlLabel, FormHelperText } from "@mui/material";
81
113
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
82
114
  function createMuiCheckboxAdapter(options) {
83
- const resolved = resolveMuiAdapterOptions(options);
84
115
  return function MuiCheckbox({
85
116
  id,
86
117
  className,
@@ -97,6 +128,9 @@ function createMuiCheckboxAdapter(options) {
97
128
  onChange,
98
129
  label
99
130
  }) {
131
+ const resolved = useResolvedMuiAdapterOptions(options);
132
+ const helperId = id === void 0 ? void 0 : ariaDescribedBy?.split(/\s+/u)[0] ?? `${id}-helper-text`;
133
+ const describedBy = ariaDescribedBy ?? (helperText === void 0 || helperText.length === 0 ? void 0 : helperId);
100
134
  return /* @__PURE__ */ jsxs(FormControl, { className, error: Boolean(error), required, disabled: disabled || readOnly, children: [
101
135
  /* @__PURE__ */ jsx2(
102
136
  FormControlLabel,
@@ -113,7 +147,7 @@ function createMuiCheckboxAdapter(options) {
113
147
  disabled: disabled || readOnly,
114
148
  inputProps: {
115
149
  "aria-label": ariaLabel,
116
- "aria-describedby": ariaDescribedBy,
150
+ "aria-describedby": describedBy,
117
151
  "aria-labelledby": ariaLabelledBy
118
152
  },
119
153
  onChange: (event) => onChange(event.target.checked)
@@ -121,7 +155,7 @@ function createMuiCheckboxAdapter(options) {
121
155
  )
122
156
  }
123
157
  ),
124
- helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx2(FormHelperText, { id: ariaDescribedBy, children: helperText })
158
+ helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx2(FormHelperText, { id: helperId, children: helperText })
125
159
  ] });
126
160
  };
127
161
  }
@@ -160,8 +194,8 @@ var MuiErrorMessageAdapter = createMuiErrorMessageAdapter();
160
194
  import { Box, Typography } from "@mui/material";
161
195
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
162
196
  function createMuiFieldsetAdapter(options) {
163
- const resolved = resolveMuiAdapterOptions(options);
164
197
  return function MuiFieldset({ className, legend, disabled, children }) {
198
+ const resolved = useResolvedMuiAdapterOptions(options);
165
199
  return /* @__PURE__ */ jsxs2(
166
200
  Box,
167
201
  {
@@ -205,7 +239,6 @@ var FALLBACK_ACTION_LABELS = {
205
239
  dragHandle: "Reorder"
206
240
  };
207
241
  function createMuiIconButtonAdapter(options) {
208
- const resolved = resolveMuiAdapterOptions(options);
209
242
  return function MuiIconButton({
210
243
  id,
211
244
  className,
@@ -219,6 +252,7 @@ function createMuiIconButtonAdapter(options) {
219
252
  actionType,
220
253
  title
221
254
  }) {
255
+ const resolved = useResolvedMuiAdapterOptions(options);
222
256
  const actionLabel = actionType === void 0 ? "Action" : resolved.getActionLabel?.(actionType) ?? FALLBACK_ACTION_LABELS[actionType];
223
257
  const tooltip = title ?? actionLabel;
224
258
  const color = actionType === "delete" ? "error" : actionType === "add" ? "primary" : "default";
@@ -246,7 +280,6 @@ var MuiIconButtonAdapter = createMuiIconButtonAdapter();
246
280
  import { Paper, Typography as Typography2 } from "@mui/material";
247
281
  import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
248
282
  function createMuiSectionAdapter(options) {
249
- const resolved = resolveMuiAdapterOptions(options);
250
283
  return function MuiSection({
251
284
  id,
252
285
  className,
@@ -257,6 +290,7 @@ function createMuiSectionAdapter(options) {
257
290
  onClickCapture,
258
291
  children
259
292
  }) {
293
+ const resolved = useResolvedMuiAdapterOptions(options);
260
294
  return /* @__PURE__ */ jsxs3(
261
295
  Paper,
262
296
  {
@@ -295,7 +329,6 @@ var MuiSectionAdapter = createMuiSectionAdapter();
295
329
  import { FormControl as FormControl2, FormHelperText as FormHelperText2, InputLabel, MenuItem, Select } from "@mui/material";
296
330
  import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
297
331
  function createMuiSelectAdapter(options) {
298
- const resolved = resolveMuiAdapterOptions(options);
299
332
  return function MuiSelect({
300
333
  id,
301
334
  className,
@@ -313,13 +346,16 @@ function createMuiSelectAdapter(options) {
313
346
  onChange,
314
347
  options: selectOptions
315
348
  }) {
349
+ const resolved = useResolvedMuiAdapterOptions(options);
316
350
  const labelId = id === void 0 || label === void 0 ? void 0 : `${id}-label`;
351
+ const helperId = id === void 0 ? void 0 : ariaDescribedBy?.split(/\s+/u)[0] ?? `${id}-helper-text`;
352
+ const describedBy = ariaDescribedBy ?? (helperText === void 0 || helperText.length === 0 ? void 0 : helperId);
317
353
  const handleChange = (event) => onChange(event.target.value);
318
354
  return /* @__PURE__ */ jsxs4(
319
355
  FormControl2,
320
356
  {
321
357
  className,
322
- fullWidth: resolved.fullWidth,
358
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
323
359
  size: resolved.size,
324
360
  variant: resolved.variant,
325
361
  error: Boolean(error),
@@ -340,13 +376,13 @@ function createMuiSelectAdapter(options) {
340
376
  readOnly,
341
377
  inputProps: {
342
378
  "aria-label": ariaLabel,
343
- "aria-describedby": ariaDescribedBy,
379
+ "aria-describedby": describedBy,
344
380
  "aria-labelledby": ariaLabelledBy
345
381
  },
346
382
  children: selectOptions.map((option) => /* @__PURE__ */ jsx7(MenuItem, { value: option.value, disabled: option.disabled, children: option.label }, option.value))
347
383
  }
348
384
  ),
349
- helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx7(FormHelperText2, { id: ariaDescribedBy, children: helperText })
385
+ helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ jsx7(FormHelperText2, { id: helperId, children: helperText })
350
386
  ]
351
387
  }
352
388
  );
@@ -358,7 +394,6 @@ var MuiSelectAdapter = createMuiSelectAdapter();
358
394
  import { TextField } from "@mui/material";
359
395
  import { jsx as jsx8 } from "react/jsx-runtime";
360
396
  function createMuiTextAreaAdapter(options) {
361
- const resolved = resolveMuiAdapterOptions(options);
362
397
  return function MuiTextArea({
363
398
  id,
364
399
  className,
@@ -378,6 +413,7 @@ function createMuiTextAreaAdapter(options) {
378
413
  maxLength,
379
414
  rows
380
415
  }) {
416
+ const resolved = useResolvedMuiAdapterOptions(options);
381
417
  return /* @__PURE__ */ jsx8(
382
418
  TextField,
383
419
  {
@@ -393,6 +429,7 @@ function createMuiTextAreaAdapter(options) {
393
429
  slotProps: {
394
430
  htmlInput: {
395
431
  maxLength,
432
+ readOnly,
396
433
  "aria-label": ariaLabel,
397
434
  "aria-describedby": ariaDescribedBy,
398
435
  "aria-labelledby": ariaLabelledBy
@@ -403,7 +440,7 @@ function createMuiTextAreaAdapter(options) {
403
440
  multiline: true,
404
441
  rows,
405
442
  placeholder,
406
- fullWidth: resolved.fullWidth,
443
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
407
444
  size: resolved.size,
408
445
  variant: resolved.variant,
409
446
  onChange: (event) => onChange(event.currentTarget.value)
@@ -417,7 +454,6 @@ var MuiTextAreaAdapter = createMuiTextAreaAdapter();
417
454
  import { TextField as TextField2 } from "@mui/material";
418
455
  import { jsx as jsx9 } from "react/jsx-runtime";
419
456
  function createMuiTextInputAdapter(options) {
420
- const resolved = resolveMuiAdapterOptions(options);
421
457
  return function MuiTextInput({
422
458
  id,
423
459
  className,
@@ -441,6 +477,7 @@ function createMuiTextInputAdapter(options) {
441
477
  max,
442
478
  step
443
479
  }) {
480
+ const resolved = useResolvedMuiAdapterOptions(options);
444
481
  return /* @__PURE__ */ jsx9(
445
482
  TextField2,
446
483
  {
@@ -460,6 +497,7 @@ function createMuiTextInputAdapter(options) {
460
497
  max,
461
498
  step,
462
499
  inputMode,
500
+ readOnly,
463
501
  "aria-label": ariaLabel,
464
502
  "aria-describedby": ariaDescribedBy,
465
503
  "aria-labelledby": ariaLabelledBy
@@ -469,7 +507,7 @@ function createMuiTextInputAdapter(options) {
469
507
  },
470
508
  type,
471
509
  placeholder,
472
- fullWidth: resolved.fullWidth,
510
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
473
511
  size: resolved.size,
474
512
  variant: resolved.variant,
475
513
  onChange: (event) => onChange(event.currentTarget.value)
@@ -517,7 +555,7 @@ function muiDefaultIconResolver(actionType) {
517
555
 
518
556
  // src/components.ts
519
557
  function isAdapterOptions(value) {
520
- return "size" in value || "variant" in value || "buttonVariant" in value || "fullWidth" in value || "dense" in value;
558
+ return "size" in value || "variant" in value || "buttonVariant" in value || "buttonVariants" in value || "fullWidth" in value || "inputFullWidth" in value || "buttonFullWidth" in value || "dense" in value || "fieldEditorOptions" in value || "localizationOptions" in value || "layoutOptions" in value || "muiSlotProps" in value || "getLocaleLabel" in value || "getActionLabel" in value;
521
559
  }
522
560
  function buildMuiBuilderComponents(options) {
523
561
  return {
@@ -533,11 +571,22 @@ function buildMuiBuilderComponents(options) {
533
571
  renderIcon: muiDefaultIconResolver
534
572
  };
535
573
  }
536
- var muiBuilderComponents = buildMuiBuilderComponents();
574
+ var muiBuilderComponents = {
575
+ Button: MuiButtonAdapter,
576
+ IconButton: MuiIconButtonAdapter,
577
+ TextInput: MuiTextInputAdapter,
578
+ TextArea: MuiTextAreaAdapter,
579
+ Select: MuiSelectAdapter,
580
+ Checkbox: MuiCheckboxAdapter,
581
+ Section: MuiSectionAdapter,
582
+ Fieldset: MuiFieldsetAdapter,
583
+ ErrorMessage: MuiErrorMessageAdapter,
584
+ renderIcon: muiDefaultIconResolver
585
+ };
537
586
  function createMuiBuilderComponents(optionsOrOverrides = {}, customOverrides) {
538
587
  const options = isAdapterOptions(optionsOrOverrides) ? optionsOrOverrides : void 0;
539
588
  const overrides = customOverrides ?? (options === void 0 ? optionsOrOverrides : {});
540
- return { ...buildMuiBuilderComponents(options), ...overrides };
589
+ return { ...options === void 0 ? muiBuilderComponents : buildMuiBuilderComponents(options), ...overrides };
541
590
  }
542
591
 
543
592
  // src/slots/FieldEditor.tsx
@@ -547,7 +596,6 @@ import { Card, Stack as Stack3, Typography as Typography3 } from "@mui/material"
547
596
  import { Stack } from "@mui/material";
548
597
  import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
549
598
  function createMuiOptionEditorSlot(options) {
550
- const resolved = resolveMuiAdapterOptions(options);
551
599
  return function MuiOptionEditor({
552
600
  field,
553
601
  option,
@@ -558,6 +606,7 @@ function createMuiOptionEditorSlot(options) {
558
606
  components,
559
607
  translate
560
608
  }) {
609
+ const resolved = useResolvedMuiAdapterOptions(options);
561
610
  const { IconButton: IconButton2, TextInput } = components;
562
611
  const describedBy = option.label.trim().length === 0 ? `mui-option-${option.id}-error` : void 0;
563
612
  return /* @__PURE__ */ jsxs5(Stack, { ...resolved.muiSlotProps?.stack, "data-mui-slot": "option-editor", spacing: resolved.dense ? 0.75 : 1, children: [
@@ -615,7 +664,7 @@ function createMuiOptionEditorSlot(options) {
615
664
  }),
616
665
  value: option.translations?.[currentLocale] ?? "",
617
666
  disabled: readOnly,
618
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "option", id: option.id }, "label", value)
667
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "option", id: option.id }, "label", value)
619
668
  }
620
669
  )
621
670
  ] });
@@ -627,7 +676,6 @@ var MuiOptionEditorSlot = createMuiOptionEditorSlot();
627
676
  import { Stack as Stack2 } from "@mui/material";
628
677
  import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
629
678
  function createMuiToolbarSlot(options) {
630
- const resolved = resolveMuiAdapterOptions(options);
631
679
  return function MuiToolbar({
632
680
  kind,
633
681
  index,
@@ -640,6 +688,7 @@ function createMuiToolbarSlot(options) {
640
688
  components,
641
689
  translate
642
690
  }) {
691
+ const resolved = useResolvedMuiAdapterOptions(options);
643
692
  const { IconButton: IconButton2 } = components;
644
693
  return /* @__PURE__ */ jsxs6(
645
694
  Stack2,
@@ -723,7 +772,6 @@ function updateBound(field, property, value) {
723
772
  return remaining;
724
773
  }
725
774
  function createMuiFieldEditorSlot(options) {
726
- const resolved = resolveMuiAdapterOptions(options);
727
775
  const Toolbar = createMuiToolbarSlot(options);
728
776
  const OptionEditor = createMuiOptionEditorSlot(options);
729
777
  return function MuiFieldEditor({
@@ -738,12 +786,14 @@ function createMuiFieldEditorSlot(options) {
738
786
  components,
739
787
  translate
740
788
  }) {
789
+ const resolved = useResolvedMuiAdapterOptions(options);
741
790
  const { Button: Button2, Checkbox: Checkbox2, Select: Select2, TextArea, TextInput } = components;
742
791
  const allowedTypes = policy?.allowedFieldTypes ?? FIELD_TYPES;
743
792
  const pageId = schema.pages?.find((page) => page.questionIds.includes(field.id))?.id ?? "";
744
793
  const condition = field.displayCondition;
745
794
  const conditionSources = schema.fields.slice(0, index);
746
795
  const conditionSource = conditionSources.find((source) => source.id === condition?.questionId);
796
+ const descriptionMode = resolved.fieldEditorOptions?.description ?? "editable";
747
797
  const titleErrorId = field.title.trim().length === 0 ? `mui-field-${field.id}-title-error` : void 0;
748
798
  return /* @__PURE__ */ jsxs7(
749
799
  Card,
@@ -807,7 +857,7 @@ function createMuiFieldEditorSlot(options) {
807
857
  }
808
858
  )
809
859
  ] }),
810
- /* @__PURE__ */ jsx13(
860
+ descriptionMode === "hidden" ? null : /* @__PURE__ */ jsx13(
811
861
  TextArea,
812
862
  {
813
863
  id: `mui-field-${field.id}-description`,
@@ -816,6 +866,7 @@ function createMuiFieldEditorSlot(options) {
816
866
  value: field.description ?? "",
817
867
  rows: resolved.dense ? 2 : 3,
818
868
  disabled: readOnly,
869
+ readOnly: descriptionMode === "readOnly",
819
870
  onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "description", value)
820
871
  }
821
872
  ),
@@ -929,17 +980,18 @@ function createMuiFieldEditorSlot(options) {
929
980
  label: translate("builder.translatedQuestionTitle"),
930
981
  value: field.translations?.[currentLocale]?.title ?? "",
931
982
  disabled: readOnly,
932
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
983
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
933
984
  }
934
985
  ),
935
- /* @__PURE__ */ jsx13(
986
+ descriptionMode === "hidden" ? null : /* @__PURE__ */ jsx13(
936
987
  TextArea,
937
988
  {
938
989
  id: `mui-field-${field.id}-${currentLocale}-description`,
939
990
  label: translate("builder.translatedDescription"),
940
991
  value: field.translations?.[currentLocale]?.description ?? "",
941
992
  disabled: readOnly,
942
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "field", id: field.id }, "description", value)
993
+ readOnly: descriptionMode === "readOnly",
994
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "field", id: field.id }, "description", value)
943
995
  }
944
996
  )
945
997
  ] }),
@@ -981,11 +1033,11 @@ var MuiFieldEditorSlot = createMuiFieldEditorSlot();
981
1033
 
982
1034
  // src/slots/Localization.tsx
983
1035
  import { ExpandMore } from "@mui/icons-material";
984
- import { Accordion, AccordionDetails, AccordionSummary, Box as Box2, Stack as Stack4, Tab, Tabs, Typography as Typography4 } from "@mui/material";
1036
+ import { Accordion, AccordionDetails, AccordionSummary, Box as Box2, Chip, Stack as Stack4, Tab, Tabs, Typography as Typography4 } from "@mui/material";
985
1037
  import { useState } from "react";
986
1038
  import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1039
+ var DEFAULT_EMPTY_STATE_MESSAGE = "No translation locales have been added yet. Select a language from the dropdown above to add one.";
987
1040
  function createMuiLocalizationSlot(options) {
988
- const resolved = resolveMuiAdapterOptions(options);
989
1041
  return function MuiLocalization({
990
1042
  schema,
991
1043
  currentLocale,
@@ -1000,6 +1052,7 @@ function createMuiLocalizationSlot(options) {
1000
1052
  components,
1001
1053
  translate
1002
1054
  }) {
1055
+ const resolved = useResolvedMuiAdapterOptions(options);
1003
1056
  const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
1004
1057
  const [newLocale, setNewLocale] = useState("");
1005
1058
  const locales = Array.from(
@@ -1024,51 +1077,93 @@ function createMuiLocalizationSlot(options) {
1024
1077
  setNewLocale("");
1025
1078
  };
1026
1079
  const stackProps = resolved.muiSlotProps?.stack;
1027
- const collapsible = resolved.localizationOptions?.collapsible ?? false;
1080
+ const localizationOptions = resolved.localizationOptions ?? {};
1081
+ const collapsible = localizationOptions.collapsible ?? false;
1082
+ const defaultLocaleControl = localizationOptions.defaultLocaleControl ?? "editable";
1083
+ const configuredTranslationLocales = locales.filter((locale) => locale !== schema.defaultLocale);
1084
+ const configuredLocales = [
1085
+ ...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
1086
+ ...configuredTranslationLocales
1087
+ ];
1088
+ const summaryLabel = configuredTranslationLocales.length === 0 ? "Translations not configured" : `${configuredLocales.length} ${configuredLocales.length === 1 ? "language" : "languages"} configured: ${configuredLocales.map(
1089
+ (locale) => locale === schema.defaultLocale ? `${resolved.getLocaleLabel?.(locale) ?? locale} (default)` : resolved.getLocaleLabel?.(locale) ?? locale
1090
+ ).join(", ")}`;
1091
+ const emptyStateMessage = localizationOptions.emptyStateMessage === void 0 ? DEFAULT_EMPTY_STATE_MESSAGE : translate(localizationOptions.emptyStateMessage);
1092
+ const title = /* @__PURE__ */ jsxs8(Stack4, { alignItems: "center", direction: "row", spacing: 1, children: [
1093
+ /* @__PURE__ */ jsx14(Typography4, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }),
1094
+ localizationOptions.showSummary ? /* @__PURE__ */ jsx14(
1095
+ Chip,
1096
+ {
1097
+ label: summaryLabel,
1098
+ size: "small",
1099
+ color: configuredTranslationLocales.length > 0 ? "primary" : "default",
1100
+ variant: "outlined"
1101
+ }
1102
+ ) : null
1103
+ ] });
1028
1104
  const content = /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1029
- !collapsible ? /* @__PURE__ */ jsx14(Typography4, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }) : null,
1030
- /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1031
- /* @__PURE__ */ jsx14(
1032
- TextInput,
1033
- {
1034
- id: "mui-builder-default-locale",
1035
- label: translate("builder.defaultLocale"),
1036
- value: schema.defaultLocale ?? "",
1037
- disabled: readOnly,
1038
- onChange: (value) => {
1039
- const result = actions.setDefaultLocale(value);
1040
- if (result.success && value === currentLocale) onCurrentLocaleChange("");
1041
- }
1042
- }
1043
- ),
1044
- availableAllowedLocales === void 0 ? /* @__PURE__ */ jsx14(
1045
- TextInput,
1046
- {
1047
- id: "mui-builder-new-locale",
1048
- label: translate("builder.addLocale"),
1049
- value: newLocale,
1050
- disabled: readOnly || localeLimitReached,
1051
- onChange: setNewLocale
1052
- }
1053
- ) : /* @__PURE__ */ jsx14(
1054
- Select2,
1055
- {
1056
- id: "mui-builder-new-locale",
1057
- label: translate("builder.addLocale"),
1058
- value: newLocale,
1059
- options: [
1060
- { value: "", label: "\u2014" },
1061
- ...availableAllowedLocales.map((locale) => ({
1062
- value: locale,
1063
- label: resolved.getLocaleLabel?.(locale) ?? locale
1064
- }))
1065
- ],
1066
- disabled: readOnly || localeLimitReached || availableAllowedLocales.length === 0,
1067
- onChange: setNewLocale
1068
- }
1069
- ),
1070
- /* @__PURE__ */ jsx14(Button2, { variant: "primary", action: "addLocale", disabled: !canAddLocale, onClick: addLocale, children: translate("builder.addLocale") })
1071
- ] }),
1105
+ !collapsible ? title : null,
1106
+ /* @__PURE__ */ jsxs8(
1107
+ Stack4,
1108
+ {
1109
+ ...stackProps,
1110
+ direction: { xs: "column", sm: "row" },
1111
+ alignItems: { xs: "stretch", sm: "center" },
1112
+ spacing: resolved.dense ? 1 : 2,
1113
+ sx: { mt: 1 },
1114
+ children: [
1115
+ 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: [
1116
+ /* @__PURE__ */ jsx14(Typography4, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
1117
+ /* @__PURE__ */ jsx14(
1118
+ Chip,
1119
+ {
1120
+ label: resolved.getLocaleLabel?.(schema.defaultLocale ?? "") ?? schema.defaultLocale ?? "",
1121
+ size: resolved.size
1122
+ }
1123
+ )
1124
+ ] }) : /* @__PURE__ */ jsx14(
1125
+ TextInput,
1126
+ {
1127
+ id: "mui-builder-default-locale",
1128
+ label: translate("builder.defaultLocale"),
1129
+ value: schema.defaultLocale ?? "",
1130
+ disabled: readOnly,
1131
+ onChange: (value) => {
1132
+ const result = actions.setDefaultLocale(value);
1133
+ if (result.success && value === currentLocale) onCurrentLocaleChange("");
1134
+ }
1135
+ }
1136
+ ) }),
1137
+ /* @__PURE__ */ jsx14(Box2, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, children: availableAllowedLocales === void 0 ? /* @__PURE__ */ jsx14(
1138
+ TextInput,
1139
+ {
1140
+ id: "mui-builder-new-locale",
1141
+ label: translate("builder.addLocale"),
1142
+ value: newLocale,
1143
+ disabled: readOnly || localeLimitReached,
1144
+ onChange: setNewLocale
1145
+ }
1146
+ ) : /* @__PURE__ */ jsx14(
1147
+ Select2,
1148
+ {
1149
+ id: "mui-builder-new-locale",
1150
+ label: translate("builder.addLocale"),
1151
+ value: newLocale,
1152
+ options: [
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,
1160
+ onChange: setNewLocale
1161
+ }
1162
+ ) }),
1163
+ /* @__PURE__ */ jsx14(Box2, { sx: { flexShrink: 0, minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx14(Button2, { variant: "primary", action: "addLocale", disabled: !canAddLocale, onClick: addLocale, children: translate("builder.addLocale") }) })
1164
+ ]
1165
+ }
1166
+ ),
1072
1167
  locales.length === 0 ? null : /* @__PURE__ */ jsx14(
1073
1168
  Tabs,
1074
1169
  {
@@ -1082,13 +1177,14 @@ function createMuiLocalizationSlot(options) {
1082
1177
  {
1083
1178
  value: locale,
1084
1179
  label: resolved.getLocaleLabel?.(locale) ?? locale,
1085
- disabled: readOnly && locale !== currentLocale
1180
+ disabled: readOnly && locale !== currentLocale,
1181
+ sx: { whiteSpace: "nowrap" }
1086
1182
  },
1087
1183
  locale
1088
1184
  ))
1089
1185
  }
1090
1186
  ),
1091
- !translationAdapterAvailable ? null : /* @__PURE__ */ jsx14(
1187
+ !translationAdapterAvailable ? null : /* @__PURE__ */ jsx14(Box2, { sx: { minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx14(
1092
1188
  Button2,
1093
1189
  {
1094
1190
  variant: "secondary",
@@ -1096,9 +1192,9 @@ function createMuiLocalizationSlot(options) {
1096
1192
  onClick: onAutoTranslate,
1097
1193
  children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
1098
1194
  }
1099
- ),
1195
+ ) }),
1100
1196
  translationError === void 0 ? null : /* @__PURE__ */ jsx14(ErrorMessage, { message: translationError }),
1101
- !editingLocaleConfigured ? /* @__PURE__ */ jsx14(Typography4, { variant: "body2", color: "text.secondary", children: translate("builder.selectLocale") }) : /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1197
+ !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: [
1102
1198
  /* @__PURE__ */ jsx14(
1103
1199
  TextInput,
1104
1200
  {
@@ -1106,7 +1202,7 @@ function createMuiLocalizationSlot(options) {
1106
1202
  label: translate("builder.translatedFormTitle"),
1107
1203
  value: schema.translations?.[currentLocale]?.title ?? "",
1108
1204
  disabled: readOnly,
1109
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "title", value)
1205
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "title", value)
1110
1206
  }
1111
1207
  ),
1112
1208
  /* @__PURE__ */ jsx14(
@@ -1116,7 +1212,7 @@ function createMuiLocalizationSlot(options) {
1116
1212
  label: translate("builder.translatedFormDescription"),
1117
1213
  value: schema.translations?.[currentLocale]?.description ?? "",
1118
1214
  disabled: readOnly,
1119
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "description", value)
1215
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "description", value)
1120
1216
  }
1121
1217
  ),
1122
1218
  /* @__PURE__ */ jsx14(
@@ -1126,16 +1222,16 @@ function createMuiLocalizationSlot(options) {
1126
1222
  label: translate("builder.translatedCompletionMessage"),
1127
1223
  value: schema.translations?.[currentLocale]?.completionMessage ?? "",
1128
1224
  disabled: readOnly,
1129
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "completionMessage", value)
1225
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "completionMessage", value)
1130
1226
  }
1131
1227
  )
1132
1228
  ] })
1133
1229
  ] });
1134
1230
  const configured = locales.length > 0;
1135
- const defaultExpanded = resolved.localizationOptions?.defaultExpanded === "when-configured" ? configured : resolved.localizationOptions?.defaultExpanded ?? false;
1231
+ const defaultExpanded = localizationOptions.defaultExpanded === "when-configured" ? configured : localizationOptions.defaultExpanded === "always" ? true : localizationOptions.defaultExpanded ?? false;
1136
1232
  if (collapsible) {
1137
1233
  return /* @__PURE__ */ jsxs8(Accordion, { ...resolved.muiSlotProps?.accordion, "data-mui-slot": "localization", defaultExpanded, children: [
1138
- /* @__PURE__ */ jsx14(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx14(ExpandMore, {}), children: /* @__PURE__ */ jsx14(Typography4, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }) }),
1234
+ /* @__PURE__ */ jsx14(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx14(ExpandMore, {}), children: title }),
1139
1235
  /* @__PURE__ */ jsx14(AccordionDetails, { children: content })
1140
1236
  ] });
1141
1237
  }
@@ -1160,10 +1256,10 @@ var MuiLocalizationSlot = createMuiLocalizationSlot();
1160
1256
  // src/slots/index.ts
1161
1257
  var muiBuilderSlots = {
1162
1258
  sectionOrder: DEFAULT_MUI_SECTION_ORDER,
1163
- toolbar: createMuiToolbarSlot(),
1164
- fieldEditor: createMuiFieldEditorSlot(),
1165
- optionEditor: createMuiOptionEditorSlot(),
1166
- localization: createMuiLocalizationSlot()
1259
+ toolbar: MuiToolbarSlot,
1260
+ fieldEditor: MuiFieldEditorSlot,
1261
+ optionEditor: MuiOptionEditorSlot,
1262
+ localization: MuiLocalizationSlot
1167
1263
  };
1168
1264
  function createMuiBuilderSlots(options, customOverrides = {}) {
1169
1265
  return {
@@ -1198,26 +1294,31 @@ function MuiFormBuilder({
1198
1294
  muiSlotProps,
1199
1295
  components: customComponents,
1200
1296
  slots: customSlots,
1297
+ sectionOrder,
1201
1298
  ...props
1202
1299
  }) {
1203
- const resolvedMuiOptions = useMemo(
1204
- () => ({
1205
- ...muiOptions,
1300
+ const contextOptions = useMemo(
1301
+ () => mergeMuiAdapterOptions(muiOptions, {
1206
1302
  ...layoutOptions === void 0 ? {} : { layoutOptions },
1207
1303
  ...localizationOptions === void 0 ? {} : { localizationOptions },
1208
1304
  ...muiSlotProps === void 0 ? {} : { muiSlotProps }
1209
1305
  }),
1210
1306
  [layoutOptions, localizationOptions, muiOptions, muiSlotProps]
1211
1307
  );
1212
- const components = useMemo(
1213
- () => createMuiBuilderComponents(resolvedMuiOptions, customComponents),
1214
- [resolvedMuiOptions, customComponents]
1215
- );
1216
- const slots = useMemo(
1217
- () => createMuiBuilderSlots(resolvedMuiOptions, customSlots),
1218
- [resolvedMuiOptions, customSlots]
1219
- );
1220
- return /* @__PURE__ */ jsx15(FormBuilder, { ...props, components, disableDefaultStyles: true, slots });
1308
+ const contextValue = useMemo(() => ({ options: contextOptions }), [contextOptions]);
1309
+ const components = useMemo(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
1310
+ const slots = useMemo(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
1311
+ const resolvedSectionOrder = sectionOrder ?? contextOptions.layoutOptions?.sectionOrder;
1312
+ return /* @__PURE__ */ jsx15(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx15(
1313
+ FormBuilder,
1314
+ {
1315
+ ...props,
1316
+ components,
1317
+ disableDefaultStyles: true,
1318
+ slots,
1319
+ ...resolvedSectionOrder === void 0 ? {} : { sectionOrder: resolvedSectionOrder }
1320
+ }
1321
+ ) });
1221
1322
  }
1222
1323
  export {
1223
1324
  DEFAULT_MUI_SECTION_ORDER,
@@ -1227,6 +1328,7 @@ export {
1227
1328
  MuiFieldEditorSlot,
1228
1329
  MuiFieldsetAdapter,
1229
1330
  MuiFormBuilder,
1331
+ MuiFormBuilderContext,
1230
1332
  MuiIconButtonAdapter,
1231
1333
  MuiLocalizationSlot,
1232
1334
  MuiOptionEditorSlot,
@@ -1251,8 +1353,10 @@ export {
1251
1353
  createMuiTextAreaAdapter,
1252
1354
  createMuiTextInputAdapter,
1253
1355
  createMuiToolbarSlot,
1356
+ mergeMuiAdapterOptions,
1254
1357
  muiBuilderComponents,
1255
1358
  muiBuilderSlots,
1256
1359
  muiDefaultIconResolver,
1257
- resolveMuiAdapterOptions
1360
+ resolveMuiAdapterOptions,
1361
+ useResolvedMuiAdapterOptions
1258
1362
  };