@form-engine-ts/mui 2.9.4 → 2.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,13 +15,20 @@ import { MuiFormBuilder } from "@form-engine-ts/mui";
15
15
  size: "small",
16
16
  variant: "outlined",
17
17
  dense: true,
18
+ inputFullWidth: true,
19
+ buttonFullWidth: false,
20
+ fieldEditorOptions: { description: "hidden" },
18
21
  getLocaleLabel: (locale) => localeNames[locale] ?? locale,
19
22
  buttonVariants: { primary: "contained", secondary: "outlined", danger: "outlined" }
20
23
  }}
21
24
  layoutOptions={{
22
25
  sectionOrder: ["basicSettings", "completionMessage", "questions", "addQuestion", "localization"]
23
26
  }}
24
- localizationOptions={{ collapsible: true, defaultExpanded: "when-configured" }}
27
+ localizationOptions={{
28
+ collapsible: true,
29
+ defaultExpanded: "when-configured",
30
+ defaultLocaleControl: "readOnly"
31
+ }}
25
32
  muiSlotProps={{ card: { sx: { p: 2 } }, accordion: { elevation: 0 } }}
26
33
  />;
27
34
  ```
@@ -38,8 +45,18 @@ All MUI builder slots use the `FormBuilder` translator for labels, actions, tool
38
45
  `getLocaleLabel` for application-specific locale names. The localization UI excludes `schema.defaultLocale` from its
39
46
  translation tabs and follows `allowedLocales` and `maxLocales` from the builder policy.
40
47
 
41
- `MuiAdapterOptions` defaults to `size: "medium"`, `variant: "outlined"`, `buttonVariant: "contained"`, and
42
- `fullWidth: true`. Set `dense` to reduce section, editor, option, and toolbar spacing. `buttonVariants` can override the
43
- MUI variant for `primary`, `secondary`, and `danger` actions independently. `layoutOptions`, `localizationOptions`, and
44
- `muiSlotProps` are also accepted in `muiOptions` for low-level factories such as `createMuiBuilderSlots`; the dedicated
45
- `MuiFormBuilder` props take precedence.
48
+ Manual edits from the form, field, and option translation controls use the React builder's `setManualTranslation`
49
+ action. Consequently, `createManualTranslationMetadata` receives the same source text and existing metadata for the MUI
50
+ slots as it does for the standard builder.
51
+
52
+ `MuiAdapterOptions` defaults to `size: "medium"`, `variant: "outlined"`, `buttonVariant: "contained"`,
53
+ `inputFullWidth: true`, and `buttonFullWidth: false`. The legacy `fullWidth` option remains the fallback for both new
54
+ width options. `fieldEditorOptions.description` and `localizationOptions.defaultLocaleControl` independently make those
55
+ controls editable, read-only, or hidden. Set `dense` to reduce section, editor, option, and toolbar spacing.
56
+ `buttonVariants` can override the MUI variant for `primary`, `secondary`, and `danger` actions independently.
57
+ `layoutOptions`, `localizationOptions`, and `muiSlotProps` are also accepted in `muiOptions` for low-level factories such
58
+ as `createMuiBuilderSlots`; the dedicated `MuiFormBuilder` props take precedence.
59
+
60
+ `MuiFormBuilder` supplies options through `MuiFormBuilderContext` to module-stable adapter and slot component types.
61
+ Controlled schema updates therefore preserve input focus and uncontrolled MUI state such as an open localization
62
+ accordion even when the parent passes inline option objects.
package/dist/index.cjs CHANGED
@@ -27,6 +27,7 @@ __export(index_exports, {
27
27
  MuiFieldEditorSlot: () => MuiFieldEditorSlot,
28
28
  MuiFieldsetAdapter: () => MuiFieldsetAdapter,
29
29
  MuiFormBuilder: () => MuiFormBuilder,
30
+ MuiFormBuilderContext: () => MuiFormBuilderContext,
30
31
  MuiIconButtonAdapter: () => MuiIconButtonAdapter,
31
32
  MuiLocalizationSlot: () => MuiLocalizationSlot,
32
33
  MuiOptionEditorSlot: () => MuiOptionEditorSlot,
@@ -51,16 +52,21 @@ __export(index_exports, {
51
52
  createMuiTextAreaAdapter: () => createMuiTextAreaAdapter,
52
53
  createMuiTextInputAdapter: () => createMuiTextInputAdapter,
53
54
  createMuiToolbarSlot: () => createMuiToolbarSlot,
55
+ mergeMuiAdapterOptions: () => mergeMuiAdapterOptions,
54
56
  muiBuilderComponents: () => muiBuilderComponents,
55
57
  muiBuilderSlots: () => muiBuilderSlots,
56
58
  muiDefaultIconResolver: () => muiDefaultIconResolver,
57
- resolveMuiAdapterOptions: () => resolveMuiAdapterOptions
59
+ resolveMuiAdapterOptions: () => resolveMuiAdapterOptions,
60
+ useResolvedMuiAdapterOptions: () => useResolvedMuiAdapterOptions
58
61
  });
59
62
  module.exports = __toCommonJS(index_exports);
60
63
 
61
64
  // src/adapters/Button.tsx
62
65
  var import_material = require("@mui/material");
63
66
 
67
+ // src/context.ts
68
+ var import_react = require("react");
69
+
64
70
  // src/types.ts
65
71
  var DEFAULT_MUI_SECTION_ORDER = [
66
72
  "basicSettings",
@@ -80,22 +86,47 @@ function resolveMuiAdapterOptions(options = {}) {
80
86
  danger: options.buttonVariants?.danger ?? buttonVariant
81
87
  },
82
88
  fullWidth: options.fullWidth ?? true,
89
+ inputFullWidth: options.inputFullWidth ?? options.fullWidth ?? true,
90
+ buttonFullWidth: options.buttonFullWidth ?? options.fullWidth ?? false,
83
91
  dense: options.dense ?? false,
84
92
  getLocaleLabel: options.getLocaleLabel ?? ((locale) => locale),
85
93
  ...options.getActionLabel === void 0 ? {} : { getActionLabel: options.getActionLabel },
86
94
  layoutOptions: options.layoutOptions ?? {},
95
+ fieldEditorOptions: {
96
+ description: options.fieldEditorOptions?.description ?? "editable"
97
+ },
87
98
  localizationOptions: {
88
99
  collapsible: options.localizationOptions?.collapsible ?? false,
89
- defaultExpanded: options.localizationOptions?.defaultExpanded ?? false
100
+ defaultExpanded: options.localizationOptions?.defaultExpanded ?? false,
101
+ defaultLocaleControl: options.localizationOptions?.defaultLocaleControl ?? "editable"
90
102
  },
91
103
  muiSlotProps: options.muiSlotProps ?? {}
92
104
  };
93
105
  }
94
106
 
107
+ // src/context.ts
108
+ var MuiFormBuilderContext = (0, import_react.createContext)({ options: {} });
109
+ function mergeMuiAdapterOptions(base = {}, overrides = {}) {
110
+ return {
111
+ ...base,
112
+ ...overrides,
113
+ ...base.buttonVariants === void 0 && overrides.buttonVariants === void 0 ? {} : { buttonVariants: { ...base.buttonVariants, ...overrides.buttonVariants } },
114
+ ...base.layoutOptions === void 0 && overrides.layoutOptions === void 0 ? {} : { layoutOptions: { ...base.layoutOptions, ...overrides.layoutOptions } },
115
+ ...base.fieldEditorOptions === void 0 && overrides.fieldEditorOptions === void 0 ? {} : { fieldEditorOptions: { ...base.fieldEditorOptions, ...overrides.fieldEditorOptions } },
116
+ ...base.localizationOptions === void 0 && overrides.localizationOptions === void 0 ? {} : { localizationOptions: { ...base.localizationOptions, ...overrides.localizationOptions } },
117
+ ...base.muiSlotProps === void 0 && overrides.muiSlotProps === void 0 ? {} : { muiSlotProps: { ...base.muiSlotProps, ...overrides.muiSlotProps } }
118
+ };
119
+ }
120
+ function useResolvedMuiAdapterOptions(overrides) {
121
+ const context = (0, import_react.useContext)(MuiFormBuilderContext);
122
+ return resolveMuiAdapterOptions(
123
+ overrides === void 0 ? context.options : mergeMuiAdapterOptions(context.options, overrides)
124
+ );
125
+ }
126
+
95
127
  // src/adapters/Button.tsx
96
128
  var import_jsx_runtime = require("react/jsx-runtime");
97
129
  function createMuiButtonAdapter(options) {
98
- const resolved = resolveMuiAdapterOptions(options);
99
130
  return function MuiButton({
100
131
  id,
101
132
  className,
@@ -111,6 +142,7 @@ function createMuiButtonAdapter(options) {
111
142
  action,
112
143
  targetId
113
144
  }) {
145
+ const resolved = useResolvedMuiAdapterOptions(options);
114
146
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
115
147
  import_material.Button,
116
148
  {
@@ -128,7 +160,7 @@ function createMuiButtonAdapter(options) {
128
160
  onClick,
129
161
  color: variant === "danger" ? "error" : "primary",
130
162
  variant: resolved.buttonVariants?.[variant ?? "primary"] ?? resolved.buttonVariant,
131
- fullWidth: resolved.fullWidth,
163
+ fullWidth: resolved.buttonFullWidth ?? false,
132
164
  children
133
165
  }
134
166
  );
@@ -140,7 +172,6 @@ var MuiButtonAdapter = createMuiButtonAdapter();
140
172
  var import_material2 = require("@mui/material");
141
173
  var import_jsx_runtime2 = require("react/jsx-runtime");
142
174
  function createMuiCheckboxAdapter(options) {
143
- const resolved = resolveMuiAdapterOptions(options);
144
175
  return function MuiCheckbox({
145
176
  id,
146
177
  className,
@@ -157,6 +188,7 @@ function createMuiCheckboxAdapter(options) {
157
188
  onChange,
158
189
  label
159
190
  }) {
191
+ const resolved = useResolvedMuiAdapterOptions(options);
160
192
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_material2.FormControl, { className, error: Boolean(error), required, disabled: disabled || readOnly, children: [
161
193
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
162
194
  import_material2.FormControlLabel,
@@ -220,8 +252,8 @@ var MuiErrorMessageAdapter = createMuiErrorMessageAdapter();
220
252
  var import_material4 = require("@mui/material");
221
253
  var import_jsx_runtime4 = require("react/jsx-runtime");
222
254
  function createMuiFieldsetAdapter(options) {
223
- const resolved = resolveMuiAdapterOptions(options);
224
255
  return function MuiFieldset({ className, legend, disabled, children }) {
256
+ const resolved = useResolvedMuiAdapterOptions(options);
225
257
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
226
258
  import_material4.Box,
227
259
  {
@@ -265,7 +297,6 @@ var FALLBACK_ACTION_LABELS = {
265
297
  dragHandle: "Reorder"
266
298
  };
267
299
  function createMuiIconButtonAdapter(options) {
268
- const resolved = resolveMuiAdapterOptions(options);
269
300
  return function MuiIconButton({
270
301
  id,
271
302
  className,
@@ -279,6 +310,7 @@ function createMuiIconButtonAdapter(options) {
279
310
  actionType,
280
311
  title
281
312
  }) {
313
+ const resolved = useResolvedMuiAdapterOptions(options);
282
314
  const actionLabel = actionType === void 0 ? "Action" : resolved.getActionLabel?.(actionType) ?? FALLBACK_ACTION_LABELS[actionType];
283
315
  const tooltip = title ?? actionLabel;
284
316
  const color = actionType === "delete" ? "error" : actionType === "add" ? "primary" : "default";
@@ -306,7 +338,6 @@ var MuiIconButtonAdapter = createMuiIconButtonAdapter();
306
338
  var import_material6 = require("@mui/material");
307
339
  var import_jsx_runtime6 = require("react/jsx-runtime");
308
340
  function createMuiSectionAdapter(options) {
309
- const resolved = resolveMuiAdapterOptions(options);
310
341
  return function MuiSection({
311
342
  id,
312
343
  className,
@@ -317,6 +348,7 @@ function createMuiSectionAdapter(options) {
317
348
  onClickCapture,
318
349
  children
319
350
  }) {
351
+ const resolved = useResolvedMuiAdapterOptions(options);
320
352
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
321
353
  import_material6.Paper,
322
354
  {
@@ -355,7 +387,6 @@ var MuiSectionAdapter = createMuiSectionAdapter();
355
387
  var import_material7 = require("@mui/material");
356
388
  var import_jsx_runtime7 = require("react/jsx-runtime");
357
389
  function createMuiSelectAdapter(options) {
358
- const resolved = resolveMuiAdapterOptions(options);
359
390
  return function MuiSelect({
360
391
  id,
361
392
  className,
@@ -373,13 +404,14 @@ function createMuiSelectAdapter(options) {
373
404
  onChange,
374
405
  options: selectOptions
375
406
  }) {
407
+ const resolved = useResolvedMuiAdapterOptions(options);
376
408
  const labelId = id === void 0 || label === void 0 ? void 0 : `${id}-label`;
377
409
  const handleChange = (event) => onChange(event.target.value);
378
410
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
379
411
  import_material7.FormControl,
380
412
  {
381
413
  className,
382
- fullWidth: resolved.fullWidth,
414
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
383
415
  size: resolved.size,
384
416
  variant: resolved.variant,
385
417
  error: Boolean(error),
@@ -418,7 +450,6 @@ var MuiSelectAdapter = createMuiSelectAdapter();
418
450
  var import_material8 = require("@mui/material");
419
451
  var import_jsx_runtime8 = require("react/jsx-runtime");
420
452
  function createMuiTextAreaAdapter(options) {
421
- const resolved = resolveMuiAdapterOptions(options);
422
453
  return function MuiTextArea({
423
454
  id,
424
455
  className,
@@ -438,6 +469,7 @@ function createMuiTextAreaAdapter(options) {
438
469
  maxLength,
439
470
  rows
440
471
  }) {
472
+ const resolved = useResolvedMuiAdapterOptions(options);
441
473
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
442
474
  import_material8.TextField,
443
475
  {
@@ -453,6 +485,7 @@ function createMuiTextAreaAdapter(options) {
453
485
  slotProps: {
454
486
  htmlInput: {
455
487
  maxLength,
488
+ readOnly,
456
489
  "aria-label": ariaLabel,
457
490
  "aria-describedby": ariaDescribedBy,
458
491
  "aria-labelledby": ariaLabelledBy
@@ -463,7 +496,7 @@ function createMuiTextAreaAdapter(options) {
463
496
  multiline: true,
464
497
  rows,
465
498
  placeholder,
466
- fullWidth: resolved.fullWidth,
499
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
467
500
  size: resolved.size,
468
501
  variant: resolved.variant,
469
502
  onChange: (event) => onChange(event.currentTarget.value)
@@ -477,7 +510,6 @@ var MuiTextAreaAdapter = createMuiTextAreaAdapter();
477
510
  var import_material9 = require("@mui/material");
478
511
  var import_jsx_runtime9 = require("react/jsx-runtime");
479
512
  function createMuiTextInputAdapter(options) {
480
- const resolved = resolveMuiAdapterOptions(options);
481
513
  return function MuiTextInput({
482
514
  id,
483
515
  className,
@@ -501,6 +533,7 @@ function createMuiTextInputAdapter(options) {
501
533
  max,
502
534
  step
503
535
  }) {
536
+ const resolved = useResolvedMuiAdapterOptions(options);
504
537
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
505
538
  import_material9.TextField,
506
539
  {
@@ -520,6 +553,7 @@ function createMuiTextInputAdapter(options) {
520
553
  max,
521
554
  step,
522
555
  inputMode,
556
+ readOnly,
523
557
  "aria-label": ariaLabel,
524
558
  "aria-describedby": ariaDescribedBy,
525
559
  "aria-labelledby": ariaLabelledBy
@@ -529,7 +563,7 @@ function createMuiTextInputAdapter(options) {
529
563
  },
530
564
  type,
531
565
  placeholder,
532
- fullWidth: resolved.fullWidth,
566
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
533
567
  size: resolved.size,
534
568
  variant: resolved.variant,
535
569
  onChange: (event) => onChange(event.currentTarget.value)
@@ -567,7 +601,7 @@ function muiDefaultIconResolver(actionType) {
567
601
 
568
602
  // src/components.ts
569
603
  function isAdapterOptions(value) {
570
- return "size" in value || "variant" in value || "buttonVariant" in value || "fullWidth" in value || "dense" in value;
604
+ 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;
571
605
  }
572
606
  function buildMuiBuilderComponents(options) {
573
607
  return {
@@ -583,11 +617,22 @@ function buildMuiBuilderComponents(options) {
583
617
  renderIcon: muiDefaultIconResolver
584
618
  };
585
619
  }
586
- var muiBuilderComponents = buildMuiBuilderComponents();
620
+ var muiBuilderComponents = {
621
+ Button: MuiButtonAdapter,
622
+ IconButton: MuiIconButtonAdapter,
623
+ TextInput: MuiTextInputAdapter,
624
+ TextArea: MuiTextAreaAdapter,
625
+ Select: MuiSelectAdapter,
626
+ Checkbox: MuiCheckboxAdapter,
627
+ Section: MuiSectionAdapter,
628
+ Fieldset: MuiFieldsetAdapter,
629
+ ErrorMessage: MuiErrorMessageAdapter,
630
+ renderIcon: muiDefaultIconResolver
631
+ };
587
632
  function createMuiBuilderComponents(optionsOrOverrides = {}, customOverrides) {
588
633
  const options = isAdapterOptions(optionsOrOverrides) ? optionsOrOverrides : void 0;
589
634
  const overrides = customOverrides ?? (options === void 0 ? optionsOrOverrides : {});
590
- return { ...buildMuiBuilderComponents(options), ...overrides };
635
+ return { ...options === void 0 ? muiBuilderComponents : buildMuiBuilderComponents(options), ...overrides };
591
636
  }
592
637
 
593
638
  // src/slots/FieldEditor.tsx
@@ -597,7 +642,6 @@ var import_material12 = require("@mui/material");
597
642
  var import_material10 = require("@mui/material");
598
643
  var import_jsx_runtime11 = require("react/jsx-runtime");
599
644
  function createMuiOptionEditorSlot(options) {
600
- const resolved = resolveMuiAdapterOptions(options);
601
645
  return function MuiOptionEditor({
602
646
  field,
603
647
  option,
@@ -608,6 +652,7 @@ function createMuiOptionEditorSlot(options) {
608
652
  components,
609
653
  translate
610
654
  }) {
655
+ const resolved = useResolvedMuiAdapterOptions(options);
611
656
  const { IconButton: IconButton2, TextInput } = components;
612
657
  const describedBy = option.label.trim().length === 0 ? `mui-option-${option.id}-error` : void 0;
613
658
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.Stack, { ...resolved.muiSlotProps?.stack, "data-mui-slot": "option-editor", spacing: resolved.dense ? 0.75 : 1, children: [
@@ -665,7 +710,7 @@ function createMuiOptionEditorSlot(options) {
665
710
  }),
666
711
  value: option.translations?.[currentLocale] ?? "",
667
712
  disabled: readOnly,
668
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "option", id: option.id }, "label", value)
713
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "option", id: option.id }, "label", value)
669
714
  }
670
715
  )
671
716
  ] });
@@ -677,7 +722,6 @@ var MuiOptionEditorSlot = createMuiOptionEditorSlot();
677
722
  var import_material11 = require("@mui/material");
678
723
  var import_jsx_runtime12 = require("react/jsx-runtime");
679
724
  function createMuiToolbarSlot(options) {
680
- const resolved = resolveMuiAdapterOptions(options);
681
725
  return function MuiToolbar({
682
726
  kind,
683
727
  index,
@@ -690,6 +734,7 @@ function createMuiToolbarSlot(options) {
690
734
  components,
691
735
  translate
692
736
  }) {
737
+ const resolved = useResolvedMuiAdapterOptions(options);
693
738
  const { IconButton: IconButton2 } = components;
694
739
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
695
740
  import_material11.Stack,
@@ -773,7 +818,6 @@ function updateBound(field, property, value) {
773
818
  return remaining;
774
819
  }
775
820
  function createMuiFieldEditorSlot(options) {
776
- const resolved = resolveMuiAdapterOptions(options);
777
821
  const Toolbar = createMuiToolbarSlot(options);
778
822
  const OptionEditor = createMuiOptionEditorSlot(options);
779
823
  return function MuiFieldEditor({
@@ -788,12 +832,14 @@ function createMuiFieldEditorSlot(options) {
788
832
  components,
789
833
  translate
790
834
  }) {
835
+ const resolved = useResolvedMuiAdapterOptions(options);
791
836
  const { Button: Button2, Checkbox: Checkbox2, Select: Select2, TextArea, TextInput } = components;
792
837
  const allowedTypes = policy?.allowedFieldTypes ?? FIELD_TYPES;
793
838
  const pageId = schema.pages?.find((page) => page.questionIds.includes(field.id))?.id ?? "";
794
839
  const condition = field.displayCondition;
795
840
  const conditionSources = schema.fields.slice(0, index);
796
841
  const conditionSource = conditionSources.find((source) => source.id === condition?.questionId);
842
+ const descriptionMode = resolved.fieldEditorOptions?.description ?? "editable";
797
843
  const titleErrorId = field.title.trim().length === 0 ? `mui-field-${field.id}-title-error` : void 0;
798
844
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
799
845
  import_material12.Card,
@@ -857,7 +903,7 @@ function createMuiFieldEditorSlot(options) {
857
903
  }
858
904
  )
859
905
  ] }),
860
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
906
+ descriptionMode === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
861
907
  TextArea,
862
908
  {
863
909
  id: `mui-field-${field.id}-description`,
@@ -866,6 +912,7 @@ function createMuiFieldEditorSlot(options) {
866
912
  value: field.description ?? "",
867
913
  rows: resolved.dense ? 2 : 3,
868
914
  disabled: readOnly,
915
+ readOnly: descriptionMode === "readOnly",
869
916
  onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "description", value)
870
917
  }
871
918
  ),
@@ -979,17 +1026,18 @@ function createMuiFieldEditorSlot(options) {
979
1026
  label: translate("builder.translatedQuestionTitle"),
980
1027
  value: field.translations?.[currentLocale]?.title ?? "",
981
1028
  disabled: readOnly,
982
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
1029
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
983
1030
  }
984
1031
  ),
985
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1032
+ descriptionMode === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
986
1033
  TextArea,
987
1034
  {
988
1035
  id: `mui-field-${field.id}-${currentLocale}-description`,
989
1036
  label: translate("builder.translatedDescription"),
990
1037
  value: field.translations?.[currentLocale]?.description ?? "",
991
1038
  disabled: readOnly,
992
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "field", id: field.id }, "description", value)
1039
+ readOnly: descriptionMode === "readOnly",
1040
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "field", id: field.id }, "description", value)
993
1041
  }
994
1042
  )
995
1043
  ] }),
@@ -1032,10 +1080,9 @@ var MuiFieldEditorSlot = createMuiFieldEditorSlot();
1032
1080
  // src/slots/Localization.tsx
1033
1081
  var import_icons_material2 = require("@mui/icons-material");
1034
1082
  var import_material13 = require("@mui/material");
1035
- var import_react = require("react");
1083
+ var import_react2 = require("react");
1036
1084
  var import_jsx_runtime14 = require("react/jsx-runtime");
1037
1085
  function createMuiLocalizationSlot(options) {
1038
- const resolved = resolveMuiAdapterOptions(options);
1039
1086
  return function MuiLocalization({
1040
1087
  schema,
1041
1088
  currentLocale,
@@ -1050,8 +1097,9 @@ function createMuiLocalizationSlot(options) {
1050
1097
  components,
1051
1098
  translate
1052
1099
  }) {
1100
+ const resolved = useResolvedMuiAdapterOptions(options);
1053
1101
  const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
1054
- const [newLocale, setNewLocale] = (0, import_react.useState)("");
1102
+ const [newLocale, setNewLocale] = (0, import_react2.useState)("");
1055
1103
  const locales = Array.from(
1056
1104
  new Set((schema.supportedLocales ?? []).filter((locale) => locale !== schema.defaultLocale))
1057
1105
  );
@@ -1075,10 +1123,20 @@ function createMuiLocalizationSlot(options) {
1075
1123
  };
1076
1124
  const stackProps = resolved.muiSlotProps?.stack;
1077
1125
  const collapsible = resolved.localizationOptions?.collapsible ?? false;
1126
+ const defaultLocaleControl = resolved.localizationOptions?.defaultLocaleControl ?? "editable";
1078
1127
  const content = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1079
1128
  !collapsible ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }) : null,
1080
1129
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1081
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1130
+ defaultLocaleControl === "hidden" ? null : defaultLocaleControl === "readOnly" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { spacing: 0.5, children: [
1131
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
1132
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1133
+ import_material13.Chip,
1134
+ {
1135
+ label: resolved.getLocaleLabel?.(schema.defaultLocale ?? "") ?? schema.defaultLocale ?? "",
1136
+ size: resolved.size
1137
+ }
1138
+ )
1139
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1082
1140
  TextInput,
1083
1141
  {
1084
1142
  id: "mui-builder-default-locale",
@@ -1156,7 +1214,7 @@ function createMuiLocalizationSlot(options) {
1156
1214
  label: translate("builder.translatedFormTitle"),
1157
1215
  value: schema.translations?.[currentLocale]?.title ?? "",
1158
1216
  disabled: readOnly,
1159
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "title", value)
1217
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "title", value)
1160
1218
  }
1161
1219
  ),
1162
1220
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
@@ -1166,7 +1224,7 @@ function createMuiLocalizationSlot(options) {
1166
1224
  label: translate("builder.translatedFormDescription"),
1167
1225
  value: schema.translations?.[currentLocale]?.description ?? "",
1168
1226
  disabled: readOnly,
1169
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "description", value)
1227
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "description", value)
1170
1228
  }
1171
1229
  ),
1172
1230
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
@@ -1176,7 +1234,7 @@ function createMuiLocalizationSlot(options) {
1176
1234
  label: translate("builder.translatedCompletionMessage"),
1177
1235
  value: schema.translations?.[currentLocale]?.completionMessage ?? "",
1178
1236
  disabled: readOnly,
1179
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "completionMessage", value)
1237
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "completionMessage", value)
1180
1238
  }
1181
1239
  )
1182
1240
  ] })
@@ -1210,10 +1268,10 @@ var MuiLocalizationSlot = createMuiLocalizationSlot();
1210
1268
  // src/slots/index.ts
1211
1269
  var muiBuilderSlots = {
1212
1270
  sectionOrder: DEFAULT_MUI_SECTION_ORDER,
1213
- toolbar: createMuiToolbarSlot(),
1214
- fieldEditor: createMuiFieldEditorSlot(),
1215
- optionEditor: createMuiOptionEditorSlot(),
1216
- localization: createMuiLocalizationSlot()
1271
+ toolbar: MuiToolbarSlot,
1272
+ fieldEditor: MuiFieldEditorSlot,
1273
+ optionEditor: MuiOptionEditorSlot,
1274
+ localization: MuiLocalizationSlot
1217
1275
  };
1218
1276
  function createMuiBuilderSlots(options, customOverrides = {}) {
1219
1277
  return {
@@ -1236,8 +1294,8 @@ function createMuiBuilderProps(options, overrides = {}) {
1236
1294
  }
1237
1295
 
1238
1296
  // src/MuiFormBuilder.tsx
1239
- var import_react2 = require("@form-engine-ts/react");
1240
- var import_react3 = require("react");
1297
+ var import_react3 = require("@form-engine-ts/react");
1298
+ var import_react4 = require("react");
1241
1299
  var import_jsx_runtime15 = require("react/jsx-runtime");
1242
1300
  function MuiFormBuilder({
1243
1301
  muiOptions,
@@ -1246,26 +1304,31 @@ function MuiFormBuilder({
1246
1304
  muiSlotProps,
1247
1305
  components: customComponents,
1248
1306
  slots: customSlots,
1307
+ sectionOrder,
1249
1308
  ...props
1250
1309
  }) {
1251
- const resolvedMuiOptions = (0, import_react3.useMemo)(
1252
- () => ({
1253
- ...muiOptions,
1310
+ const contextOptions = (0, import_react4.useMemo)(
1311
+ () => mergeMuiAdapterOptions(muiOptions, {
1254
1312
  ...layoutOptions === void 0 ? {} : { layoutOptions },
1255
1313
  ...localizationOptions === void 0 ? {} : { localizationOptions },
1256
1314
  ...muiSlotProps === void 0 ? {} : { muiSlotProps }
1257
1315
  }),
1258
1316
  [layoutOptions, localizationOptions, muiOptions, muiSlotProps]
1259
1317
  );
1260
- const components = (0, import_react3.useMemo)(
1261
- () => createMuiBuilderComponents(resolvedMuiOptions, customComponents),
1262
- [resolvedMuiOptions, customComponents]
1263
- );
1264
- const slots = (0, import_react3.useMemo)(
1265
- () => createMuiBuilderSlots(resolvedMuiOptions, customSlots),
1266
- [resolvedMuiOptions, customSlots]
1267
- );
1268
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react2.FormBuilder, { ...props, components, disableDefaultStyles: true, slots });
1318
+ const contextValue = (0, import_react4.useMemo)(() => ({ options: contextOptions }), [contextOptions]);
1319
+ const components = (0, import_react4.useMemo)(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
1320
+ const slots = (0, import_react4.useMemo)(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
1321
+ const resolvedSectionOrder = sectionOrder ?? contextOptions.layoutOptions?.sectionOrder;
1322
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1323
+ import_react3.FormBuilder,
1324
+ {
1325
+ ...props,
1326
+ components,
1327
+ disableDefaultStyles: true,
1328
+ slots,
1329
+ ...resolvedSectionOrder === void 0 ? {} : { sectionOrder: resolvedSectionOrder }
1330
+ }
1331
+ ) });
1269
1332
  }
1270
1333
  // Annotate the CommonJS export names for ESM import in node:
1271
1334
  0 && (module.exports = {
@@ -1276,6 +1339,7 @@ function MuiFormBuilder({
1276
1339
  MuiFieldEditorSlot,
1277
1340
  MuiFieldsetAdapter,
1278
1341
  MuiFormBuilder,
1342
+ MuiFormBuilderContext,
1279
1343
  MuiIconButtonAdapter,
1280
1344
  MuiLocalizationSlot,
1281
1345
  MuiOptionEditorSlot,
@@ -1300,8 +1364,10 @@ function MuiFormBuilder({
1300
1364
  createMuiTextAreaAdapter,
1301
1365
  createMuiTextInputAdapter,
1302
1366
  createMuiToolbarSlot,
1367
+ mergeMuiAdapterOptions,
1303
1368
  muiBuilderComponents,
1304
1369
  muiBuilderSlots,
1305
1370
  muiDefaultIconResolver,
1306
- resolveMuiAdapterOptions
1371
+ resolveMuiAdapterOptions,
1372
+ useResolvedMuiAdapterOptions
1307
1373
  });
package/dist/index.d.cts CHANGED
@@ -11,6 +11,10 @@ interface MuiLayoutOptions {
11
11
  interface MuiLocalizationOptions {
12
12
  readonly collapsible?: boolean;
13
13
  readonly defaultExpanded?: boolean | "when-configured";
14
+ readonly defaultLocaleControl?: "editable" | "readOnly" | "hidden";
15
+ }
16
+ interface MuiFieldEditorOptions {
17
+ readonly description?: "editable" | "readOnly" | "hidden";
14
18
  }
15
19
  interface MuiBuilderSlotProps {
16
20
  readonly card?: Partial<CardProps>;
@@ -28,10 +32,13 @@ interface MuiAdapterOptions {
28
32
  readonly danger?: MuiButtonVariant;
29
33
  };
30
34
  readonly fullWidth?: boolean;
35
+ readonly inputFullWidth?: boolean;
36
+ readonly buttonFullWidth?: boolean;
31
37
  readonly dense?: boolean;
32
38
  readonly getLocaleLabel?: (locale: string) => string;
33
39
  readonly getActionLabel?: (actionType: BuilderActionIconType) => string;
34
40
  readonly layoutOptions?: MuiLayoutOptions;
41
+ readonly fieldEditorOptions?: MuiFieldEditorOptions;
35
42
  readonly localizationOptions?: MuiLocalizationOptions;
36
43
  readonly muiSlotProps?: MuiBuilderSlotProps;
37
44
  }
@@ -45,10 +52,13 @@ interface ResolvedMuiAdapterOptions {
45
52
  readonly danger: MuiButtonVariant;
46
53
  };
47
54
  readonly fullWidth: boolean;
55
+ readonly inputFullWidth?: boolean;
56
+ readonly buttonFullWidth?: boolean;
48
57
  readonly dense: boolean;
49
58
  readonly getLocaleLabel?: (locale: string) => string;
50
59
  readonly getActionLabel?: (actionType: BuilderActionIconType) => string;
51
60
  readonly layoutOptions?: MuiLayoutOptions;
61
+ readonly fieldEditorOptions?: MuiFieldEditorOptions;
52
62
  readonly localizationOptions?: MuiLocalizationOptions;
53
63
  readonly muiSlotProps?: MuiBuilderSlotProps;
54
64
  }
@@ -92,6 +102,13 @@ declare const muiBuilderComponents: FormBuilderComponents;
92
102
  declare function createMuiBuilderComponents(customOverrides?: Partial<FormBuilderComponents>): FormBuilderComponents;
93
103
  declare function createMuiBuilderComponents(options?: MuiAdapterOptions, customOverrides?: Partial<FormBuilderComponents>): FormBuilderComponents;
94
104
 
105
+ interface MuiFormBuilderContextValue {
106
+ readonly options: MuiAdapterOptions;
107
+ }
108
+ declare const MuiFormBuilderContext: react.Context<MuiFormBuilderContextValue>;
109
+ declare function mergeMuiAdapterOptions(base?: MuiAdapterOptions, overrides?: MuiAdapterOptions): MuiAdapterOptions;
110
+ declare function useResolvedMuiAdapterOptions(overrides?: MuiAdapterOptions): ResolvedMuiAdapterOptions;
111
+
95
112
  declare function muiDefaultIconResolver(actionType: BuilderActionIconType): ReactNode;
96
113
 
97
114
  interface MuiFormBuilderProps extends Omit<FormBuilderProps, "components" | "disableDefaultStyles" | "slots" | "unstyled"> {
@@ -102,7 +119,7 @@ interface MuiFormBuilderProps extends Omit<FormBuilderProps, "components" | "dis
102
119
  readonly components?: Partial<FormBuilderComponents>;
103
120
  readonly slots?: Partial<FormBuilderSlots>;
104
121
  }
105
- declare function MuiFormBuilder({ muiOptions, layoutOptions, localizationOptions, muiSlotProps, components: customComponents, slots: customSlots, ...props }: MuiFormBuilderProps): react.JSX.Element;
122
+ declare function MuiFormBuilder({ muiOptions, layoutOptions, localizationOptions, muiSlotProps, components: customComponents, slots: customSlots, sectionOrder, ...props }: MuiFormBuilderProps): react.JSX.Element;
106
123
 
107
124
  declare function createMuiFieldEditorSlot(options?: MuiAdapterOptions): ComponentType<BuilderFieldEditorSlotProps>;
108
125
  declare const MuiFieldEditorSlot: NonNullable<FormBuilderSlots["fieldEditor"]>;
@@ -119,4 +136,4 @@ declare const MuiToolbarSlot: NonNullable<FormBuilderSlots["toolbar"]>;
119
136
  declare const muiBuilderSlots: FormBuilderSlots;
120
137
  declare function createMuiBuilderSlots(options?: MuiAdapterOptions, customOverrides?: Partial<FormBuilderSlots>): FormBuilderSlots;
121
138
 
122
- export { type BuilderSectionName, DEFAULT_MUI_SECTION_ORDER, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiErrorMessageAdapter, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, 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, muiBuilderComponents, muiBuilderSlots, muiDefaultIconResolver, resolveMuiAdapterOptions };
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 };
package/dist/index.d.ts CHANGED
@@ -11,6 +11,10 @@ interface MuiLayoutOptions {
11
11
  interface MuiLocalizationOptions {
12
12
  readonly collapsible?: boolean;
13
13
  readonly defaultExpanded?: boolean | "when-configured";
14
+ readonly defaultLocaleControl?: "editable" | "readOnly" | "hidden";
15
+ }
16
+ interface MuiFieldEditorOptions {
17
+ readonly description?: "editable" | "readOnly" | "hidden";
14
18
  }
15
19
  interface MuiBuilderSlotProps {
16
20
  readonly card?: Partial<CardProps>;
@@ -28,10 +32,13 @@ interface MuiAdapterOptions {
28
32
  readonly danger?: MuiButtonVariant;
29
33
  };
30
34
  readonly fullWidth?: boolean;
35
+ readonly inputFullWidth?: boolean;
36
+ readonly buttonFullWidth?: boolean;
31
37
  readonly dense?: boolean;
32
38
  readonly getLocaleLabel?: (locale: string) => string;
33
39
  readonly getActionLabel?: (actionType: BuilderActionIconType) => string;
34
40
  readonly layoutOptions?: MuiLayoutOptions;
41
+ readonly fieldEditorOptions?: MuiFieldEditorOptions;
35
42
  readonly localizationOptions?: MuiLocalizationOptions;
36
43
  readonly muiSlotProps?: MuiBuilderSlotProps;
37
44
  }
@@ -45,10 +52,13 @@ interface ResolvedMuiAdapterOptions {
45
52
  readonly danger: MuiButtonVariant;
46
53
  };
47
54
  readonly fullWidth: boolean;
55
+ readonly inputFullWidth?: boolean;
56
+ readonly buttonFullWidth?: boolean;
48
57
  readonly dense: boolean;
49
58
  readonly getLocaleLabel?: (locale: string) => string;
50
59
  readonly getActionLabel?: (actionType: BuilderActionIconType) => string;
51
60
  readonly layoutOptions?: MuiLayoutOptions;
61
+ readonly fieldEditorOptions?: MuiFieldEditorOptions;
52
62
  readonly localizationOptions?: MuiLocalizationOptions;
53
63
  readonly muiSlotProps?: MuiBuilderSlotProps;
54
64
  }
@@ -92,6 +102,13 @@ declare const muiBuilderComponents: FormBuilderComponents;
92
102
  declare function createMuiBuilderComponents(customOverrides?: Partial<FormBuilderComponents>): FormBuilderComponents;
93
103
  declare function createMuiBuilderComponents(options?: MuiAdapterOptions, customOverrides?: Partial<FormBuilderComponents>): FormBuilderComponents;
94
104
 
105
+ interface MuiFormBuilderContextValue {
106
+ readonly options: MuiAdapterOptions;
107
+ }
108
+ declare const MuiFormBuilderContext: react.Context<MuiFormBuilderContextValue>;
109
+ declare function mergeMuiAdapterOptions(base?: MuiAdapterOptions, overrides?: MuiAdapterOptions): MuiAdapterOptions;
110
+ declare function useResolvedMuiAdapterOptions(overrides?: MuiAdapterOptions): ResolvedMuiAdapterOptions;
111
+
95
112
  declare function muiDefaultIconResolver(actionType: BuilderActionIconType): ReactNode;
96
113
 
97
114
  interface MuiFormBuilderProps extends Omit<FormBuilderProps, "components" | "disableDefaultStyles" | "slots" | "unstyled"> {
@@ -102,7 +119,7 @@ interface MuiFormBuilderProps extends Omit<FormBuilderProps, "components" | "dis
102
119
  readonly components?: Partial<FormBuilderComponents>;
103
120
  readonly slots?: Partial<FormBuilderSlots>;
104
121
  }
105
- declare function MuiFormBuilder({ muiOptions, layoutOptions, localizationOptions, muiSlotProps, components: customComponents, slots: customSlots, ...props }: MuiFormBuilderProps): react.JSX.Element;
122
+ declare function MuiFormBuilder({ muiOptions, layoutOptions, localizationOptions, muiSlotProps, components: customComponents, slots: customSlots, sectionOrder, ...props }: MuiFormBuilderProps): react.JSX.Element;
106
123
 
107
124
  declare function createMuiFieldEditorSlot(options?: MuiAdapterOptions): ComponentType<BuilderFieldEditorSlotProps>;
108
125
  declare const MuiFieldEditorSlot: NonNullable<FormBuilderSlots["fieldEditor"]>;
@@ -119,4 +136,4 @@ declare const MuiToolbarSlot: NonNullable<FormBuilderSlots["toolbar"]>;
119
136
  declare const muiBuilderSlots: FormBuilderSlots;
120
137
  declare function createMuiBuilderSlots(options?: MuiAdapterOptions, customOverrides?: Partial<FormBuilderSlots>): FormBuilderSlots;
121
138
 
122
- export { type BuilderSectionName, DEFAULT_MUI_SECTION_ORDER, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiErrorMessageAdapter, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, 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, muiBuilderComponents, muiBuilderSlots, muiDefaultIconResolver, resolveMuiAdapterOptions };
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 };
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,47 @@ 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
+ defaultLocaleControl: options.localizationOptions?.defaultLocaleControl ?? "editable"
30
39
  },
31
40
  muiSlotProps: options.muiSlotProps ?? {}
32
41
  };
33
42
  }
34
43
 
44
+ // src/context.ts
45
+ var MuiFormBuilderContext = createContext({ options: {} });
46
+ function mergeMuiAdapterOptions(base = {}, overrides = {}) {
47
+ return {
48
+ ...base,
49
+ ...overrides,
50
+ ...base.buttonVariants === void 0 && overrides.buttonVariants === void 0 ? {} : { buttonVariants: { ...base.buttonVariants, ...overrides.buttonVariants } },
51
+ ...base.layoutOptions === void 0 && overrides.layoutOptions === void 0 ? {} : { layoutOptions: { ...base.layoutOptions, ...overrides.layoutOptions } },
52
+ ...base.fieldEditorOptions === void 0 && overrides.fieldEditorOptions === void 0 ? {} : { fieldEditorOptions: { ...base.fieldEditorOptions, ...overrides.fieldEditorOptions } },
53
+ ...base.localizationOptions === void 0 && overrides.localizationOptions === void 0 ? {} : { localizationOptions: { ...base.localizationOptions, ...overrides.localizationOptions } },
54
+ ...base.muiSlotProps === void 0 && overrides.muiSlotProps === void 0 ? {} : { muiSlotProps: { ...base.muiSlotProps, ...overrides.muiSlotProps } }
55
+ };
56
+ }
57
+ function useResolvedMuiAdapterOptions(overrides) {
58
+ const context = useContext(MuiFormBuilderContext);
59
+ return resolveMuiAdapterOptions(
60
+ overrides === void 0 ? context.options : mergeMuiAdapterOptions(context.options, overrides)
61
+ );
62
+ }
63
+
35
64
  // src/adapters/Button.tsx
36
65
  import { jsx } from "react/jsx-runtime";
37
66
  function createMuiButtonAdapter(options) {
38
- const resolved = resolveMuiAdapterOptions(options);
39
67
  return function MuiButton({
40
68
  id,
41
69
  className,
@@ -51,6 +79,7 @@ function createMuiButtonAdapter(options) {
51
79
  action,
52
80
  targetId
53
81
  }) {
82
+ const resolved = useResolvedMuiAdapterOptions(options);
54
83
  return /* @__PURE__ */ jsx(
55
84
  Button,
56
85
  {
@@ -68,7 +97,7 @@ function createMuiButtonAdapter(options) {
68
97
  onClick,
69
98
  color: variant === "danger" ? "error" : "primary",
70
99
  variant: resolved.buttonVariants?.[variant ?? "primary"] ?? resolved.buttonVariant,
71
- fullWidth: resolved.fullWidth,
100
+ fullWidth: resolved.buttonFullWidth ?? false,
72
101
  children
73
102
  }
74
103
  );
@@ -80,7 +109,6 @@ var MuiButtonAdapter = createMuiButtonAdapter();
80
109
  import { Checkbox, FormControl, FormControlLabel, FormHelperText } from "@mui/material";
81
110
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
82
111
  function createMuiCheckboxAdapter(options) {
83
- const resolved = resolveMuiAdapterOptions(options);
84
112
  return function MuiCheckbox({
85
113
  id,
86
114
  className,
@@ -97,6 +125,7 @@ function createMuiCheckboxAdapter(options) {
97
125
  onChange,
98
126
  label
99
127
  }) {
128
+ const resolved = useResolvedMuiAdapterOptions(options);
100
129
  return /* @__PURE__ */ jsxs(FormControl, { className, error: Boolean(error), required, disabled: disabled || readOnly, children: [
101
130
  /* @__PURE__ */ jsx2(
102
131
  FormControlLabel,
@@ -160,8 +189,8 @@ var MuiErrorMessageAdapter = createMuiErrorMessageAdapter();
160
189
  import { Box, Typography } from "@mui/material";
161
190
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
162
191
  function createMuiFieldsetAdapter(options) {
163
- const resolved = resolveMuiAdapterOptions(options);
164
192
  return function MuiFieldset({ className, legend, disabled, children }) {
193
+ const resolved = useResolvedMuiAdapterOptions(options);
165
194
  return /* @__PURE__ */ jsxs2(
166
195
  Box,
167
196
  {
@@ -205,7 +234,6 @@ var FALLBACK_ACTION_LABELS = {
205
234
  dragHandle: "Reorder"
206
235
  };
207
236
  function createMuiIconButtonAdapter(options) {
208
- const resolved = resolveMuiAdapterOptions(options);
209
237
  return function MuiIconButton({
210
238
  id,
211
239
  className,
@@ -219,6 +247,7 @@ function createMuiIconButtonAdapter(options) {
219
247
  actionType,
220
248
  title
221
249
  }) {
250
+ const resolved = useResolvedMuiAdapterOptions(options);
222
251
  const actionLabel = actionType === void 0 ? "Action" : resolved.getActionLabel?.(actionType) ?? FALLBACK_ACTION_LABELS[actionType];
223
252
  const tooltip = title ?? actionLabel;
224
253
  const color = actionType === "delete" ? "error" : actionType === "add" ? "primary" : "default";
@@ -246,7 +275,6 @@ var MuiIconButtonAdapter = createMuiIconButtonAdapter();
246
275
  import { Paper, Typography as Typography2 } from "@mui/material";
247
276
  import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
248
277
  function createMuiSectionAdapter(options) {
249
- const resolved = resolveMuiAdapterOptions(options);
250
278
  return function MuiSection({
251
279
  id,
252
280
  className,
@@ -257,6 +285,7 @@ function createMuiSectionAdapter(options) {
257
285
  onClickCapture,
258
286
  children
259
287
  }) {
288
+ const resolved = useResolvedMuiAdapterOptions(options);
260
289
  return /* @__PURE__ */ jsxs3(
261
290
  Paper,
262
291
  {
@@ -295,7 +324,6 @@ var MuiSectionAdapter = createMuiSectionAdapter();
295
324
  import { FormControl as FormControl2, FormHelperText as FormHelperText2, InputLabel, MenuItem, Select } from "@mui/material";
296
325
  import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
297
326
  function createMuiSelectAdapter(options) {
298
- const resolved = resolveMuiAdapterOptions(options);
299
327
  return function MuiSelect({
300
328
  id,
301
329
  className,
@@ -313,13 +341,14 @@ function createMuiSelectAdapter(options) {
313
341
  onChange,
314
342
  options: selectOptions
315
343
  }) {
344
+ const resolved = useResolvedMuiAdapterOptions(options);
316
345
  const labelId = id === void 0 || label === void 0 ? void 0 : `${id}-label`;
317
346
  const handleChange = (event) => onChange(event.target.value);
318
347
  return /* @__PURE__ */ jsxs4(
319
348
  FormControl2,
320
349
  {
321
350
  className,
322
- fullWidth: resolved.fullWidth,
351
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
323
352
  size: resolved.size,
324
353
  variant: resolved.variant,
325
354
  error: Boolean(error),
@@ -358,7 +387,6 @@ var MuiSelectAdapter = createMuiSelectAdapter();
358
387
  import { TextField } from "@mui/material";
359
388
  import { jsx as jsx8 } from "react/jsx-runtime";
360
389
  function createMuiTextAreaAdapter(options) {
361
- const resolved = resolveMuiAdapterOptions(options);
362
390
  return function MuiTextArea({
363
391
  id,
364
392
  className,
@@ -378,6 +406,7 @@ function createMuiTextAreaAdapter(options) {
378
406
  maxLength,
379
407
  rows
380
408
  }) {
409
+ const resolved = useResolvedMuiAdapterOptions(options);
381
410
  return /* @__PURE__ */ jsx8(
382
411
  TextField,
383
412
  {
@@ -393,6 +422,7 @@ function createMuiTextAreaAdapter(options) {
393
422
  slotProps: {
394
423
  htmlInput: {
395
424
  maxLength,
425
+ readOnly,
396
426
  "aria-label": ariaLabel,
397
427
  "aria-describedby": ariaDescribedBy,
398
428
  "aria-labelledby": ariaLabelledBy
@@ -403,7 +433,7 @@ function createMuiTextAreaAdapter(options) {
403
433
  multiline: true,
404
434
  rows,
405
435
  placeholder,
406
- fullWidth: resolved.fullWidth,
436
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
407
437
  size: resolved.size,
408
438
  variant: resolved.variant,
409
439
  onChange: (event) => onChange(event.currentTarget.value)
@@ -417,7 +447,6 @@ var MuiTextAreaAdapter = createMuiTextAreaAdapter();
417
447
  import { TextField as TextField2 } from "@mui/material";
418
448
  import { jsx as jsx9 } from "react/jsx-runtime";
419
449
  function createMuiTextInputAdapter(options) {
420
- const resolved = resolveMuiAdapterOptions(options);
421
450
  return function MuiTextInput({
422
451
  id,
423
452
  className,
@@ -441,6 +470,7 @@ function createMuiTextInputAdapter(options) {
441
470
  max,
442
471
  step
443
472
  }) {
473
+ const resolved = useResolvedMuiAdapterOptions(options);
444
474
  return /* @__PURE__ */ jsx9(
445
475
  TextField2,
446
476
  {
@@ -460,6 +490,7 @@ function createMuiTextInputAdapter(options) {
460
490
  max,
461
491
  step,
462
492
  inputMode,
493
+ readOnly,
463
494
  "aria-label": ariaLabel,
464
495
  "aria-describedby": ariaDescribedBy,
465
496
  "aria-labelledby": ariaLabelledBy
@@ -469,7 +500,7 @@ function createMuiTextInputAdapter(options) {
469
500
  },
470
501
  type,
471
502
  placeholder,
472
- fullWidth: resolved.fullWidth,
503
+ fullWidth: resolved.inputFullWidth ?? resolved.fullWidth,
473
504
  size: resolved.size,
474
505
  variant: resolved.variant,
475
506
  onChange: (event) => onChange(event.currentTarget.value)
@@ -517,7 +548,7 @@ function muiDefaultIconResolver(actionType) {
517
548
 
518
549
  // src/components.ts
519
550
  function isAdapterOptions(value) {
520
- return "size" in value || "variant" in value || "buttonVariant" in value || "fullWidth" in value || "dense" in value;
551
+ 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
552
  }
522
553
  function buildMuiBuilderComponents(options) {
523
554
  return {
@@ -533,11 +564,22 @@ function buildMuiBuilderComponents(options) {
533
564
  renderIcon: muiDefaultIconResolver
534
565
  };
535
566
  }
536
- var muiBuilderComponents = buildMuiBuilderComponents();
567
+ var muiBuilderComponents = {
568
+ Button: MuiButtonAdapter,
569
+ IconButton: MuiIconButtonAdapter,
570
+ TextInput: MuiTextInputAdapter,
571
+ TextArea: MuiTextAreaAdapter,
572
+ Select: MuiSelectAdapter,
573
+ Checkbox: MuiCheckboxAdapter,
574
+ Section: MuiSectionAdapter,
575
+ Fieldset: MuiFieldsetAdapter,
576
+ ErrorMessage: MuiErrorMessageAdapter,
577
+ renderIcon: muiDefaultIconResolver
578
+ };
537
579
  function createMuiBuilderComponents(optionsOrOverrides = {}, customOverrides) {
538
580
  const options = isAdapterOptions(optionsOrOverrides) ? optionsOrOverrides : void 0;
539
581
  const overrides = customOverrides ?? (options === void 0 ? optionsOrOverrides : {});
540
- return { ...buildMuiBuilderComponents(options), ...overrides };
582
+ return { ...options === void 0 ? muiBuilderComponents : buildMuiBuilderComponents(options), ...overrides };
541
583
  }
542
584
 
543
585
  // src/slots/FieldEditor.tsx
@@ -547,7 +589,6 @@ import { Card, Stack as Stack3, Typography as Typography3 } from "@mui/material"
547
589
  import { Stack } from "@mui/material";
548
590
  import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
549
591
  function createMuiOptionEditorSlot(options) {
550
- const resolved = resolveMuiAdapterOptions(options);
551
592
  return function MuiOptionEditor({
552
593
  field,
553
594
  option,
@@ -558,6 +599,7 @@ function createMuiOptionEditorSlot(options) {
558
599
  components,
559
600
  translate
560
601
  }) {
602
+ const resolved = useResolvedMuiAdapterOptions(options);
561
603
  const { IconButton: IconButton2, TextInput } = components;
562
604
  const describedBy = option.label.trim().length === 0 ? `mui-option-${option.id}-error` : void 0;
563
605
  return /* @__PURE__ */ jsxs5(Stack, { ...resolved.muiSlotProps?.stack, "data-mui-slot": "option-editor", spacing: resolved.dense ? 0.75 : 1, children: [
@@ -615,7 +657,7 @@ function createMuiOptionEditorSlot(options) {
615
657
  }),
616
658
  value: option.translations?.[currentLocale] ?? "",
617
659
  disabled: readOnly,
618
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "option", id: option.id }, "label", value)
660
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "option", id: option.id }, "label", value)
619
661
  }
620
662
  )
621
663
  ] });
@@ -627,7 +669,6 @@ var MuiOptionEditorSlot = createMuiOptionEditorSlot();
627
669
  import { Stack as Stack2 } from "@mui/material";
628
670
  import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
629
671
  function createMuiToolbarSlot(options) {
630
- const resolved = resolveMuiAdapterOptions(options);
631
672
  return function MuiToolbar({
632
673
  kind,
633
674
  index,
@@ -640,6 +681,7 @@ function createMuiToolbarSlot(options) {
640
681
  components,
641
682
  translate
642
683
  }) {
684
+ const resolved = useResolvedMuiAdapterOptions(options);
643
685
  const { IconButton: IconButton2 } = components;
644
686
  return /* @__PURE__ */ jsxs6(
645
687
  Stack2,
@@ -723,7 +765,6 @@ function updateBound(field, property, value) {
723
765
  return remaining;
724
766
  }
725
767
  function createMuiFieldEditorSlot(options) {
726
- const resolved = resolveMuiAdapterOptions(options);
727
768
  const Toolbar = createMuiToolbarSlot(options);
728
769
  const OptionEditor = createMuiOptionEditorSlot(options);
729
770
  return function MuiFieldEditor({
@@ -738,12 +779,14 @@ function createMuiFieldEditorSlot(options) {
738
779
  components,
739
780
  translate
740
781
  }) {
782
+ const resolved = useResolvedMuiAdapterOptions(options);
741
783
  const { Button: Button2, Checkbox: Checkbox2, Select: Select2, TextArea, TextInput } = components;
742
784
  const allowedTypes = policy?.allowedFieldTypes ?? FIELD_TYPES;
743
785
  const pageId = schema.pages?.find((page) => page.questionIds.includes(field.id))?.id ?? "";
744
786
  const condition = field.displayCondition;
745
787
  const conditionSources = schema.fields.slice(0, index);
746
788
  const conditionSource = conditionSources.find((source) => source.id === condition?.questionId);
789
+ const descriptionMode = resolved.fieldEditorOptions?.description ?? "editable";
747
790
  const titleErrorId = field.title.trim().length === 0 ? `mui-field-${field.id}-title-error` : void 0;
748
791
  return /* @__PURE__ */ jsxs7(
749
792
  Card,
@@ -807,7 +850,7 @@ function createMuiFieldEditorSlot(options) {
807
850
  }
808
851
  )
809
852
  ] }),
810
- /* @__PURE__ */ jsx13(
853
+ descriptionMode === "hidden" ? null : /* @__PURE__ */ jsx13(
811
854
  TextArea,
812
855
  {
813
856
  id: `mui-field-${field.id}-description`,
@@ -816,6 +859,7 @@ function createMuiFieldEditorSlot(options) {
816
859
  value: field.description ?? "",
817
860
  rows: resolved.dense ? 2 : 3,
818
861
  disabled: readOnly,
862
+ readOnly: descriptionMode === "readOnly",
819
863
  onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "description", value)
820
864
  }
821
865
  ),
@@ -929,17 +973,18 @@ function createMuiFieldEditorSlot(options) {
929
973
  label: translate("builder.translatedQuestionTitle"),
930
974
  value: field.translations?.[currentLocale]?.title ?? "",
931
975
  disabled: readOnly,
932
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
976
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
933
977
  }
934
978
  ),
935
- /* @__PURE__ */ jsx13(
979
+ descriptionMode === "hidden" ? null : /* @__PURE__ */ jsx13(
936
980
  TextArea,
937
981
  {
938
982
  id: `mui-field-${field.id}-${currentLocale}-description`,
939
983
  label: translate("builder.translatedDescription"),
940
984
  value: field.translations?.[currentLocale]?.description ?? "",
941
985
  disabled: readOnly,
942
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "field", id: field.id }, "description", value)
986
+ readOnly: descriptionMode === "readOnly",
987
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "field", id: field.id }, "description", value)
943
988
  }
944
989
  )
945
990
  ] }),
@@ -981,11 +1026,10 @@ var MuiFieldEditorSlot = createMuiFieldEditorSlot();
981
1026
 
982
1027
  // src/slots/Localization.tsx
983
1028
  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";
1029
+ import { Accordion, AccordionDetails, AccordionSummary, Box as Box2, Chip, Stack as Stack4, Tab, Tabs, Typography as Typography4 } from "@mui/material";
985
1030
  import { useState } from "react";
986
1031
  import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
987
1032
  function createMuiLocalizationSlot(options) {
988
- const resolved = resolveMuiAdapterOptions(options);
989
1033
  return function MuiLocalization({
990
1034
  schema,
991
1035
  currentLocale,
@@ -1000,6 +1044,7 @@ function createMuiLocalizationSlot(options) {
1000
1044
  components,
1001
1045
  translate
1002
1046
  }) {
1047
+ const resolved = useResolvedMuiAdapterOptions(options);
1003
1048
  const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
1004
1049
  const [newLocale, setNewLocale] = useState("");
1005
1050
  const locales = Array.from(
@@ -1025,10 +1070,20 @@ function createMuiLocalizationSlot(options) {
1025
1070
  };
1026
1071
  const stackProps = resolved.muiSlotProps?.stack;
1027
1072
  const collapsible = resolved.localizationOptions?.collapsible ?? false;
1073
+ const defaultLocaleControl = resolved.localizationOptions?.defaultLocaleControl ?? "editable";
1028
1074
  const content = /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1029
1075
  !collapsible ? /* @__PURE__ */ jsx14(Typography4, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }) : null,
1030
1076
  /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1031
- /* @__PURE__ */ jsx14(
1077
+ defaultLocaleControl === "hidden" ? null : defaultLocaleControl === "readOnly" ? /* @__PURE__ */ jsxs8(Stack4, { spacing: 0.5, children: [
1078
+ /* @__PURE__ */ jsx14(Typography4, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
1079
+ /* @__PURE__ */ jsx14(
1080
+ Chip,
1081
+ {
1082
+ label: resolved.getLocaleLabel?.(schema.defaultLocale ?? "") ?? schema.defaultLocale ?? "",
1083
+ size: resolved.size
1084
+ }
1085
+ )
1086
+ ] }) : /* @__PURE__ */ jsx14(
1032
1087
  TextInput,
1033
1088
  {
1034
1089
  id: "mui-builder-default-locale",
@@ -1106,7 +1161,7 @@ function createMuiLocalizationSlot(options) {
1106
1161
  label: translate("builder.translatedFormTitle"),
1107
1162
  value: schema.translations?.[currentLocale]?.title ?? "",
1108
1163
  disabled: readOnly,
1109
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "title", value)
1164
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "title", value)
1110
1165
  }
1111
1166
  ),
1112
1167
  /* @__PURE__ */ jsx14(
@@ -1116,7 +1171,7 @@ function createMuiLocalizationSlot(options) {
1116
1171
  label: translate("builder.translatedFormDescription"),
1117
1172
  value: schema.translations?.[currentLocale]?.description ?? "",
1118
1173
  disabled: readOnly,
1119
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "description", value)
1174
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "description", value)
1120
1175
  }
1121
1176
  ),
1122
1177
  /* @__PURE__ */ jsx14(
@@ -1126,7 +1181,7 @@ function createMuiLocalizationSlot(options) {
1126
1181
  label: translate("builder.translatedCompletionMessage"),
1127
1182
  value: schema.translations?.[currentLocale]?.completionMessage ?? "",
1128
1183
  disabled: readOnly,
1129
- onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "completionMessage", value)
1184
+ onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "completionMessage", value)
1130
1185
  }
1131
1186
  )
1132
1187
  ] })
@@ -1160,10 +1215,10 @@ var MuiLocalizationSlot = createMuiLocalizationSlot();
1160
1215
  // src/slots/index.ts
1161
1216
  var muiBuilderSlots = {
1162
1217
  sectionOrder: DEFAULT_MUI_SECTION_ORDER,
1163
- toolbar: createMuiToolbarSlot(),
1164
- fieldEditor: createMuiFieldEditorSlot(),
1165
- optionEditor: createMuiOptionEditorSlot(),
1166
- localization: createMuiLocalizationSlot()
1218
+ toolbar: MuiToolbarSlot,
1219
+ fieldEditor: MuiFieldEditorSlot,
1220
+ optionEditor: MuiOptionEditorSlot,
1221
+ localization: MuiLocalizationSlot
1167
1222
  };
1168
1223
  function createMuiBuilderSlots(options, customOverrides = {}) {
1169
1224
  return {
@@ -1198,26 +1253,31 @@ function MuiFormBuilder({
1198
1253
  muiSlotProps,
1199
1254
  components: customComponents,
1200
1255
  slots: customSlots,
1256
+ sectionOrder,
1201
1257
  ...props
1202
1258
  }) {
1203
- const resolvedMuiOptions = useMemo(
1204
- () => ({
1205
- ...muiOptions,
1259
+ const contextOptions = useMemo(
1260
+ () => mergeMuiAdapterOptions(muiOptions, {
1206
1261
  ...layoutOptions === void 0 ? {} : { layoutOptions },
1207
1262
  ...localizationOptions === void 0 ? {} : { localizationOptions },
1208
1263
  ...muiSlotProps === void 0 ? {} : { muiSlotProps }
1209
1264
  }),
1210
1265
  [layoutOptions, localizationOptions, muiOptions, muiSlotProps]
1211
1266
  );
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 });
1267
+ const contextValue = useMemo(() => ({ options: contextOptions }), [contextOptions]);
1268
+ const components = useMemo(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
1269
+ const slots = useMemo(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
1270
+ const resolvedSectionOrder = sectionOrder ?? contextOptions.layoutOptions?.sectionOrder;
1271
+ return /* @__PURE__ */ jsx15(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx15(
1272
+ FormBuilder,
1273
+ {
1274
+ ...props,
1275
+ components,
1276
+ disableDefaultStyles: true,
1277
+ slots,
1278
+ ...resolvedSectionOrder === void 0 ? {} : { sectionOrder: resolvedSectionOrder }
1279
+ }
1280
+ ) });
1221
1281
  }
1222
1282
  export {
1223
1283
  DEFAULT_MUI_SECTION_ORDER,
@@ -1227,6 +1287,7 @@ export {
1227
1287
  MuiFieldEditorSlot,
1228
1288
  MuiFieldsetAdapter,
1229
1289
  MuiFormBuilder,
1290
+ MuiFormBuilderContext,
1230
1291
  MuiIconButtonAdapter,
1231
1292
  MuiLocalizationSlot,
1232
1293
  MuiOptionEditorSlot,
@@ -1251,8 +1312,10 @@ export {
1251
1312
  createMuiTextAreaAdapter,
1252
1313
  createMuiTextInputAdapter,
1253
1314
  createMuiToolbarSlot,
1315
+ mergeMuiAdapterOptions,
1254
1316
  muiBuilderComponents,
1255
1317
  muiBuilderSlots,
1256
1318
  muiDefaultIconResolver,
1257
- resolveMuiAdapterOptions
1319
+ resolveMuiAdapterOptions,
1320
+ useResolvedMuiAdapterOptions
1258
1321
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@form-engine-ts/mui",
3
- "version": "2.9.4",
3
+ "version": "2.9.5",
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/react": "2.9.4",
50
- "@form-engine-ts/core": "2.9.4"
49
+ "@form-engine-ts/core": "2.9.5",
50
+ "@form-engine-ts/react": "2.9.5"
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": "2.9.4",
62
- "@form-engine-ts/react": "2.9.4"
61
+ "@form-engine-ts/core": "2.9.5",
62
+ "@form-engine-ts/react": "2.9.5"
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",