@form-engine-ts/mui 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -753,11 +753,199 @@ function createMuiBuilderComponents(optionsOrOverrides = {}, customOverrides) {
753
753
  // src/slots/FieldEditor.tsx
754
754
  import { DEFAULT_FIELD_TYPE_DEFINITIONS } from "@form-engine-ts/core";
755
755
  import { resolveFieldEditorControls, resolveFieldTypeSelectOptions } from "@form-engine-ts/react";
756
- import { Card, Stack as Stack3, Typography as Typography3 } from "@mui/material";
756
+ import { Card, Stack as Stack4, Typography as Typography3 } from "@mui/material";
757
757
 
758
- // src/slots/OptionEditor.tsx
759
- import { Stack } from "@mui/material";
758
+ // src/slots/ConditionEditor.tsx
759
+ import {
760
+ Button as Button2,
761
+ FormControl as FormControl3,
762
+ InputLabel as InputLabel2,
763
+ MenuItem as MenuItem2,
764
+ Select as Select2,
765
+ Stack,
766
+ TextField as TextField3,
767
+ ToggleButton,
768
+ ToggleButtonGroup
769
+ } from "@mui/material";
760
770
  import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
771
+ var OPERATORS = [
772
+ "equals",
773
+ "not_equals",
774
+ "contains",
775
+ "not_contains",
776
+ "is_empty",
777
+ "is_not_empty",
778
+ "greater_than",
779
+ "less_than"
780
+ ];
781
+ function sourceIds(field) {
782
+ if (field.displayRule === void 0)
783
+ return field.displayCondition?.questionId === void 0 ? [] : [field.displayCondition.questionId];
784
+ const ids = [];
785
+ const visit = (group) => {
786
+ for (const condition of group.conditions) {
787
+ if ("logic" in condition) visit(condition);
788
+ else ids.push(condition.fieldId);
789
+ }
790
+ };
791
+ visit(field.displayRule.condition);
792
+ return ids;
793
+ }
794
+ function dependsOn(schema, startId, targetId, visited = /* @__PURE__ */ new Set()) {
795
+ if (startId === targetId) return true;
796
+ if (visited.has(startId)) return false;
797
+ visited.add(startId);
798
+ const field = schema.fields.find((candidate) => candidate.id === startId);
799
+ return field !== void 0 && sourceIds(field).some((sourceId) => dependsOn(schema, sourceId, targetId, visited));
800
+ }
801
+ function operatorsFor(field) {
802
+ if (field === void 0) return [];
803
+ if (field.type === "checkbox" || field.type === "multi-select")
804
+ return ["contains", "not_contains", "is_empty", "is_not_empty"];
805
+ if (field.type === "text" || field.type === "textarea")
806
+ return OPERATORS.filter(
807
+ (operator) => ["equals", "not_equals", "contains", "not_contains", "is_empty", "is_not_empty"].includes(operator)
808
+ );
809
+ if (field.type === "number" || field.type === "rating")
810
+ return ["equals", "not_equals", "greater_than", "less_than", "is_empty", "is_not_empty"];
811
+ return ["equals", "not_equals", "is_empty", "is_not_empty"];
812
+ }
813
+ function conditionGroup(rule) {
814
+ return rule?.condition ?? { logic: "all", conditions: [] };
815
+ }
816
+ function conditionValue(field, condition, onChange) {
817
+ if (["is_empty", "is_not_empty"].includes(condition.operator)) return null;
818
+ if (field !== void 0 && "options" in field) {
819
+ return /* @__PURE__ */ jsxs5(FormControl3, { fullWidth: true, size: "small", children: [
820
+ /* @__PURE__ */ jsx11(InputLabel2, { children: "Value" }),
821
+ /* @__PURE__ */ jsx11(Select2, { label: "Value", value: String(condition.value ?? ""), onChange: (event) => onChange(event.target.value), children: field.options.map((option) => /* @__PURE__ */ jsx11(MenuItem2, { value: option.id, children: option.label }, option.id)) })
822
+ ] });
823
+ }
824
+ return /* @__PURE__ */ jsx11(
825
+ TextField3,
826
+ {
827
+ label: "Value",
828
+ type: field?.type === "number" || field?.type === "rating" ? "number" : "text",
829
+ value: condition.value === void 0 ? "" : String(condition.value),
830
+ onChange: (event) => onChange(field?.type === "number" || field?.type === "rating" ? Number(event.target.value) : event.target.value),
831
+ fullWidth: true,
832
+ size: "small"
833
+ }
834
+ );
835
+ }
836
+ function ConditionEditor({ schema, fieldId, value, onChange, readOnly = false }) {
837
+ const group = conditionGroup(value);
838
+ const candidates = schema.fields.filter((field) => field.id !== fieldId && !dependsOn(schema, field.id, fieldId));
839
+ const updateGroup = (nextGroup) => onChange({ action: value?.action ?? "show", condition: nextGroup });
840
+ const updateCondition = (index, nextCondition) => {
841
+ const conditions = group.conditions.map(
842
+ (condition, conditionIndex) => conditionIndex === index ? nextCondition : condition
843
+ );
844
+ updateGroup({ ...group, conditions });
845
+ };
846
+ return /* @__PURE__ */ jsxs5(Stack, { spacing: 1.5, "data-testid": `condition-editor-${fieldId}`, children: [
847
+ /* @__PURE__ */ jsxs5(
848
+ ToggleButtonGroup,
849
+ {
850
+ exclusive: true,
851
+ value: group.logic,
852
+ onChange: (_event, logic) => logic === null ? void 0 : updateGroup({ ...group, logic }),
853
+ disabled: readOnly,
854
+ size: "small",
855
+ children: [
856
+ /* @__PURE__ */ jsx11(ToggleButton, { value: "all", children: "All (AND)" }),
857
+ /* @__PURE__ */ jsx11(ToggleButton, { value: "any", children: "Any (OR)" })
858
+ ]
859
+ }
860
+ ),
861
+ /* @__PURE__ */ jsxs5(FormControl3, { fullWidth: true, size: "small", children: [
862
+ /* @__PURE__ */ jsx11(InputLabel2, { children: "Action" }),
863
+ /* @__PURE__ */ jsxs5(
864
+ Select2,
865
+ {
866
+ label: "Action",
867
+ value: value?.action ?? "show",
868
+ onChange: (event) => onChange({ action: event.target.value, condition: group }),
869
+ disabled: readOnly,
870
+ children: [
871
+ /* @__PURE__ */ jsx11(MenuItem2, { value: "show", children: "Show when matched" }),
872
+ /* @__PURE__ */ jsx11(MenuItem2, { value: "hide", children: "Hide when matched" })
873
+ ]
874
+ }
875
+ )
876
+ ] }),
877
+ group.conditions.map((condition, index) => {
878
+ if ("logic" in condition) return null;
879
+ const source = schema.fields.find((field) => field.id === condition.fieldId);
880
+ return /* @__PURE__ */ jsxs5(Stack, { direction: { xs: "column", md: "row" }, spacing: 1, children: [
881
+ /* @__PURE__ */ jsxs5(FormControl3, { fullWidth: true, size: "small", children: [
882
+ /* @__PURE__ */ jsx11(InputLabel2, { children: "Question" }),
883
+ /* @__PURE__ */ jsx11(
884
+ Select2,
885
+ {
886
+ label: "Question",
887
+ value: condition.fieldId,
888
+ onChange: (event) => {
889
+ const nextSource = schema.fields.find((field) => field.id === event.target.value);
890
+ const nextOperator = operatorsFor(nextSource)[0] ?? "equals";
891
+ updateCondition(index, { fieldId: event.target.value, operator: nextOperator });
892
+ },
893
+ disabled: readOnly,
894
+ children: candidates.map((candidate) => /* @__PURE__ */ jsx11(MenuItem2, { value: candidate.id, children: candidate.title }, candidate.id))
895
+ }
896
+ )
897
+ ] }),
898
+ /* @__PURE__ */ jsxs5(FormControl3, { fullWidth: true, size: "small", children: [
899
+ /* @__PURE__ */ jsx11(InputLabel2, { children: "Operator" }),
900
+ /* @__PURE__ */ jsx11(
901
+ Select2,
902
+ {
903
+ label: "Operator",
904
+ value: condition.operator,
905
+ onChange: (event) => updateCondition(index, { ...condition, operator: event.target.value }),
906
+ disabled: readOnly,
907
+ children: operatorsFor(source).map((operator) => /* @__PURE__ */ jsx11(MenuItem2, { value: operator, children: operator }, operator))
908
+ }
909
+ )
910
+ ] }),
911
+ conditionValue(
912
+ source,
913
+ condition,
914
+ (nextValue) => updateCondition(index, { ...condition, value: nextValue })
915
+ ),
916
+ /* @__PURE__ */ jsx11(
917
+ Button2,
918
+ {
919
+ onClick: () => updateGroup({
920
+ ...group,
921
+ conditions: group.conditions.filter((_item, itemIndex) => itemIndex !== index)
922
+ }),
923
+ disabled: readOnly,
924
+ children: "Remove"
925
+ }
926
+ )
927
+ ] }, `${condition.fieldId}-${condition.operator}`);
928
+ }),
929
+ /* @__PURE__ */ jsx11(
930
+ Button2,
931
+ {
932
+ variant: "outlined",
933
+ disabled: readOnly || candidates.length === 0,
934
+ onClick: () => {
935
+ const source = candidates[0];
936
+ if (source === void 0) return;
937
+ const operator = operatorsFor(source)[0] ?? "equals";
938
+ updateGroup({ ...group, conditions: [...group.conditions, { fieldId: source.id, operator }] });
939
+ },
940
+ children: "Add condition"
941
+ }
942
+ )
943
+ ] });
944
+ }
945
+
946
+ // src/slots/OptionEditor.tsx
947
+ import { Stack as Stack2 } from "@mui/material";
948
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
761
949
  function createMuiOptionEditorSlot(options) {
762
950
  return function MuiOptionEditor({
763
951
  field,
@@ -772,9 +960,9 @@ function createMuiOptionEditorSlot(options) {
772
960
  const resolved = useResolvedMuiAdapterOptions(options);
773
961
  const { IconButton: IconButton2, TextInput } = components;
774
962
  const describedBy = option.label.trim().length === 0 ? `mui-option-${option.id}-error` : void 0;
775
- return /* @__PURE__ */ jsxs5(Stack, { ...resolved.muiSlotProps?.stack, "data-mui-slot": "option-editor", spacing: resolved.dense ? 0.75 : 1, children: [
776
- /* @__PURE__ */ jsxs5(Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, alignItems: { sm: "flex-start" }, children: [
777
- /* @__PURE__ */ jsx11(
963
+ return /* @__PURE__ */ jsxs6(Stack2, { ...resolved.muiSlotProps?.stack, "data-mui-slot": "option-editor", spacing: resolved.dense ? 0.75 : 1, children: [
964
+ /* @__PURE__ */ jsxs6(Stack2, { direction: { xs: "column", sm: "row" }, spacing: 1, alignItems: { sm: "flex-start" }, children: [
965
+ /* @__PURE__ */ jsx12(
778
966
  TextInput,
779
967
  {
780
968
  id: `mui-option-${option.id}`,
@@ -788,8 +976,8 @@ function createMuiOptionEditorSlot(options) {
788
976
  onChange: (value) => actions.updateOption(field.id, option.id, (current) => ({ ...current, label: value }))
789
977
  }
790
978
  ),
791
- /* @__PURE__ */ jsxs5(Stack, { direction: "row", spacing: 0.5, children: [
792
- /* @__PURE__ */ jsx11(
979
+ /* @__PURE__ */ jsxs6(Stack2, { direction: "row", spacing: 0.5, children: [
980
+ /* @__PURE__ */ jsx12(
793
981
  IconButton2,
794
982
  {
795
983
  actionType: "moveUp",
@@ -798,7 +986,7 @@ function createMuiOptionEditorSlot(options) {
798
986
  onClick: () => actions.moveOption(field.id, option.id, index - 1)
799
987
  }
800
988
  ),
801
- /* @__PURE__ */ jsx11(
989
+ /* @__PURE__ */ jsx12(
802
990
  IconButton2,
803
991
  {
804
992
  actionType: "moveDown",
@@ -807,7 +995,7 @@ function createMuiOptionEditorSlot(options) {
807
995
  onClick: () => actions.moveOption(field.id, option.id, index + 1)
808
996
  }
809
997
  ),
810
- /* @__PURE__ */ jsx11(
998
+ /* @__PURE__ */ jsx12(
811
999
  IconButton2,
812
1000
  {
813
1001
  actionType: "delete",
@@ -818,7 +1006,7 @@ function createMuiOptionEditorSlot(options) {
818
1006
  )
819
1007
  ] })
820
1008
  ] }),
821
- currentLocale.length === 0 ? null : /* @__PURE__ */ jsx11(
1009
+ currentLocale.length === 0 ? null : /* @__PURE__ */ jsx12(
822
1010
  TextInput,
823
1011
  {
824
1012
  id: `mui-option-${option.id}-${currentLocale}`,
@@ -836,8 +1024,8 @@ function createMuiOptionEditorSlot(options) {
836
1024
  var MuiOptionEditorSlot = createMuiOptionEditorSlot();
837
1025
 
838
1026
  // src/slots/Toolbar.tsx
839
- import { Stack as Stack2 } from "@mui/material";
840
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
1027
+ import { Stack as Stack3 } from "@mui/material";
1028
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
841
1029
  function createMuiToolbarSlot(options) {
842
1030
  return function MuiToolbar({
843
1031
  kind,
@@ -853,8 +1041,8 @@ function createMuiToolbarSlot(options) {
853
1041
  }) {
854
1042
  const resolved = useResolvedMuiAdapterOptions(options);
855
1043
  const { IconButton: IconButton2 } = components;
856
- return /* @__PURE__ */ jsxs6(
857
- Stack2,
1044
+ return /* @__PURE__ */ jsxs7(
1045
+ Stack3,
858
1046
  {
859
1047
  ...resolved.muiSlotProps?.stack,
860
1048
  "data-mui-slot": "toolbar",
@@ -863,7 +1051,7 @@ function createMuiToolbarSlot(options) {
863
1051
  alignItems: "center",
864
1052
  sx: resolved.muiSlotProps?.stack?.sx ?? { mb: resolved.dense ? 1 : 2 },
865
1053
  children: [
866
- /* @__PURE__ */ jsx12(
1054
+ /* @__PURE__ */ jsx13(
867
1055
  IconButton2,
868
1056
  {
869
1057
  actionType: "moveUp",
@@ -872,7 +1060,7 @@ function createMuiToolbarSlot(options) {
872
1060
  onClick: onMoveUp
873
1061
  }
874
1062
  ),
875
- /* @__PURE__ */ jsx12(
1063
+ /* @__PURE__ */ jsx13(
876
1064
  IconButton2,
877
1065
  {
878
1066
  actionType: "moveDown",
@@ -881,7 +1069,7 @@ function createMuiToolbarSlot(options) {
881
1069
  onClick: onMoveDown
882
1070
  }
883
1071
  ),
884
- /* @__PURE__ */ jsx12(
1072
+ /* @__PURE__ */ jsx13(
885
1073
  IconButton2,
886
1074
  {
887
1075
  actionType: "delete",
@@ -898,7 +1086,7 @@ function createMuiToolbarSlot(options) {
898
1086
  var MuiToolbarSlot = createMuiToolbarSlot();
899
1087
 
900
1088
  // src/slots/FieldEditor.tsx
901
- import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1089
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
902
1090
  var FIELD_TYPES = DEFAULT_FIELD_TYPE_DEFINITIONS.map((definition) => definition.type);
903
1091
  function isFieldType(value) {
904
1092
  return FIELD_TYPES.some((type) => type === value);
@@ -951,7 +1139,7 @@ function createMuiFieldEditorSlot(options) {
951
1139
  fieldTypeOptions: fieldTypeOptionsConfig
952
1140
  }) {
953
1141
  const resolved = useResolvedMuiAdapterOptions(options);
954
- const { Button: Button2, Checkbox: Checkbox2, Select: Select2, TextArea, TextInput } = components;
1142
+ const { Button: Button4, Checkbox: Checkbox2, Select: Select3, TextArea, TextInput } = components;
955
1143
  const allowedTypes = policy?.allowedFieldTypes ?? FIELD_TYPES;
956
1144
  const pageId = schema.pages?.find((page) => page.questionIds.includes(field.id))?.id ?? "";
957
1145
  const condition = field.displayCondition;
@@ -995,7 +1183,7 @@ function createMuiFieldEditorSlot(options) {
995
1183
  const changeFieldType = (nextType) => {
996
1184
  if (allowedTypes.includes(nextType)) actions.changeFieldType(field.id, nextType);
997
1185
  };
998
- return /* @__PURE__ */ jsxs7(
1186
+ return /* @__PURE__ */ jsxs8(
999
1187
  Card,
1000
1188
  {
1001
1189
  ...resolved.muiSlotProps?.card,
@@ -1003,8 +1191,8 @@ function createMuiFieldEditorSlot(options) {
1003
1191
  variant: "outlined",
1004
1192
  sx: resolved.muiSlotProps?.card?.sx ?? { mb: resolved.dense ? 1 : 2, p: resolved.dense ? 1.5 : 2 },
1005
1193
  children: [
1006
- FieldEditorHeader === void 0 ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
1007
- /* @__PURE__ */ jsx13(
1194
+ FieldEditorHeader === void 0 ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
1195
+ /* @__PURE__ */ jsx14(
1008
1196
  Toolbar,
1009
1197
  {
1010
1198
  schema,
@@ -1022,11 +1210,11 @@ function createMuiFieldEditorSlot(options) {
1022
1210
  components
1023
1211
  }
1024
1212
  ),
1025
- /* @__PURE__ */ jsx13(Typography3, { variant: "subtitle1", fontWeight: "bold", children: field.title })
1026
- ] }) : /* @__PURE__ */ jsx13(FieldEditorHeader, { field, index, totalFields: schema.fields.length, actions }),
1027
- /* @__PURE__ */ jsxs7(Stack3, { ...resolved.muiSlotProps?.stack, spacing: resolved.dense ? 1 : 2, children: [
1028
- /* @__PURE__ */ jsxs7(Stack3, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1029
- controls.title === "hidden" ? null : /* @__PURE__ */ jsx13(
1213
+ /* @__PURE__ */ jsx14(Typography3, { variant: "subtitle1", fontWeight: "bold", children: field.title })
1214
+ ] }) : /* @__PURE__ */ jsx14(FieldEditorHeader, { field, index, totalFields: schema.fields.length, actions }),
1215
+ /* @__PURE__ */ jsxs8(Stack4, { ...resolved.muiSlotProps?.stack, spacing: resolved.dense ? 1 : 2, children: [
1216
+ /* @__PURE__ */ jsxs8(Stack4, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1217
+ controls.title === "hidden" ? null : /* @__PURE__ */ jsx14(
1030
1218
  TextInput,
1031
1219
  {
1032
1220
  id: `mui-field-${field.id}-title`,
@@ -1041,8 +1229,8 @@ function createMuiFieldEditorSlot(options) {
1041
1229
  onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "title", value)
1042
1230
  }
1043
1231
  ),
1044
- controls.typeSelect === "hidden" ? null : FieldTypeSelect === void 0 ? /* @__PURE__ */ jsx13(
1045
- Select2,
1232
+ controls.typeSelect === "hidden" ? null : FieldTypeSelect === void 0 ? /* @__PURE__ */ jsx14(
1233
+ Select3,
1046
1234
  {
1047
1235
  id: fieldTypeSelectId,
1048
1236
  name: `fields.${field.id}.type`,
@@ -1054,7 +1242,7 @@ function createMuiFieldEditorSlot(options) {
1054
1242
  if (isFieldType(value)) changeFieldType(value);
1055
1243
  }
1056
1244
  }
1057
- ) : /* @__PURE__ */ jsx13(
1245
+ ) : /* @__PURE__ */ jsx14(
1058
1246
  FieldTypeSelect,
1059
1247
  {
1060
1248
  id: fieldTypeSelectId,
@@ -1071,7 +1259,7 @@ function createMuiFieldEditorSlot(options) {
1071
1259
  }
1072
1260
  )
1073
1261
  ] }),
1074
- controls.description === "hidden" ? null : /* @__PURE__ */ jsx13(
1262
+ controls.description === "hidden" ? null : /* @__PURE__ */ jsx14(
1075
1263
  TextArea,
1076
1264
  {
1077
1265
  id: `mui-field-${field.id}-description`,
@@ -1084,7 +1272,7 @@ function createMuiFieldEditorSlot(options) {
1084
1272
  onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "description", value)
1085
1273
  }
1086
1274
  ),
1087
- controls.required === "hidden" ? null : /* @__PURE__ */ jsx13(
1275
+ controls.required === "hidden" ? null : /* @__PURE__ */ jsx14(
1088
1276
  Checkbox2,
1089
1277
  {
1090
1278
  id: `mui-field-${field.id}-required`,
@@ -1095,8 +1283,8 @@ function createMuiFieldEditorSlot(options) {
1095
1283
  onChange: (checked) => actions.updateField(field.id, (current) => ({ ...current, required: checked }))
1096
1284
  }
1097
1285
  ),
1098
- features?.pages === false || schema.pages === void 0 ? null : /* @__PURE__ */ jsx13(
1099
- Select2,
1286
+ features?.pages === false || schema.pages === void 0 ? null : /* @__PURE__ */ jsx14(
1287
+ Select3,
1100
1288
  {
1101
1289
  id: `mui-field-${field.id}-page`,
1102
1290
  label: translate("builder.questionPage"),
@@ -1109,8 +1297,8 @@ function createMuiFieldEditorSlot(options) {
1109
1297
  onChange: (value) => actions.assignFieldToPage(field.id, value.length === 0 ? null : value)
1110
1298
  }
1111
1299
  ),
1112
- field.type === "number" || field.type === "rating" ? (field.type === "number" ? controls.numberLimits : controls.ratingBounds) === "hidden" ? null : /* @__PURE__ */ jsxs7(Stack3, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1113
- /* @__PURE__ */ jsx13(
1300
+ field.type === "number" || field.type === "rating" ? (field.type === "number" ? controls.numberLimits : controls.ratingBounds) === "hidden" ? null : /* @__PURE__ */ jsxs8(Stack4, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1301
+ /* @__PURE__ */ jsx14(
1114
1302
  TextInput,
1115
1303
  {
1116
1304
  id: `mui-field-${field.id}-minimum`,
@@ -1121,7 +1309,7 @@ function createMuiFieldEditorSlot(options) {
1121
1309
  onChange: (value) => actions.updateField(field.id, (current) => updateBound(current, "min", value))
1122
1310
  }
1123
1311
  ),
1124
- /* @__PURE__ */ jsx13(
1312
+ /* @__PURE__ */ jsx14(
1125
1313
  TextInput,
1126
1314
  {
1127
1315
  id: `mui-field-${field.id}-maximum`,
@@ -1133,7 +1321,7 @@ function createMuiFieldEditorSlot(options) {
1133
1321
  }
1134
1322
  )
1135
1323
  ] }) : null,
1136
- field.type === "number" && controls.numberLimits !== "hidden" ? /* @__PURE__ */ jsx13(
1324
+ field.type === "number" && controls.numberLimits !== "hidden" ? /* @__PURE__ */ jsx14(
1137
1325
  TextInput,
1138
1326
  {
1139
1327
  id: `mui-field-${field.id}-step`,
@@ -1144,8 +1332,8 @@ function createMuiFieldEditorSlot(options) {
1144
1332
  onChange: (value) => actions.updateField(field.id, (current) => updateNumberProperty(current, "step", value))
1145
1333
  }
1146
1334
  ) : null,
1147
- (field.type === "text" || field.type === "textarea") && controls.textLimits !== "hidden" ? /* @__PURE__ */ jsxs7(Stack3, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1148
- /* @__PURE__ */ jsx13(
1335
+ (field.type === "text" || field.type === "textarea") && controls.textLimits !== "hidden" ? /* @__PURE__ */ jsxs8(Stack4, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1336
+ /* @__PURE__ */ jsx14(
1149
1337
  TextInput,
1150
1338
  {
1151
1339
  id: `mui-field-${field.id}-min-length`,
@@ -1160,7 +1348,7 @@ function createMuiFieldEditorSlot(options) {
1160
1348
  })
1161
1349
  }
1162
1350
  ),
1163
- /* @__PURE__ */ jsx13(
1351
+ /* @__PURE__ */ jsx14(
1164
1352
  TextInput,
1165
1353
  {
1166
1354
  id: `mui-field-${field.id}-max-length`,
@@ -1175,7 +1363,7 @@ function createMuiFieldEditorSlot(options) {
1175
1363
  })
1176
1364
  }
1177
1365
  ),
1178
- /* @__PURE__ */ jsx13(
1366
+ /* @__PURE__ */ jsx14(
1179
1367
  TextInput,
1180
1368
  {
1181
1369
  id: `mui-field-${field.id}-pattern`,
@@ -1189,9 +1377,25 @@ function createMuiFieldEditorSlot(options) {
1189
1377
  }
1190
1378
  )
1191
1379
  ] }) : null,
1192
- features?.conditions === false || conditionSources.length === 0 || controls.displayConditions === "hidden" ? null : /* @__PURE__ */ jsxs7(Stack3, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1193
- /* @__PURE__ */ jsx13(
1194
- Select2,
1380
+ features?.conditions === false || conditionSources.length === 0 || controls.displayConditions === "hidden" ? null : field.displayRule !== void 0 ? /* @__PURE__ */ jsx14(
1381
+ ConditionEditor,
1382
+ {
1383
+ schema,
1384
+ fieldId: field.id,
1385
+ value: field.displayRule,
1386
+ readOnly: readOnly || controls.displayConditions === "readOnly",
1387
+ onChange: (displayRule) => actions.updateField(field.id, (current) => {
1388
+ const { displayCondition: _displayCondition, ...withoutLegacyCondition } = current;
1389
+ if (displayRule === void 0) {
1390
+ const { displayRule: _displayRule, ...withoutRules } = withoutLegacyCondition;
1391
+ return withoutRules;
1392
+ }
1393
+ return { ...withoutLegacyCondition, displayRule };
1394
+ })
1395
+ }
1396
+ ) : /* @__PURE__ */ jsxs8(Stack4, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1397
+ /* @__PURE__ */ jsx14(
1398
+ Select3,
1195
1399
  {
1196
1400
  id: `mui-field-${field.id}-condition-source`,
1197
1401
  label: translate("builder.displayCondition"),
@@ -1207,9 +1411,9 @@ function createMuiFieldEditorSlot(options) {
1207
1411
  )
1208
1412
  }
1209
1413
  ),
1210
- condition === void 0 ? null : /* @__PURE__ */ jsxs7(Fragment2, { children: [
1211
- /* @__PURE__ */ jsx13(
1212
- Select2,
1414
+ condition === void 0 ? null : /* @__PURE__ */ jsxs8(Fragment2, { children: [
1415
+ /* @__PURE__ */ jsx14(
1416
+ Select3,
1213
1417
  {
1214
1418
  id: `mui-field-${field.id}-condition-operator`,
1215
1419
  label: translate("builder.conditionOperator"),
@@ -1227,7 +1431,7 @@ function createMuiFieldEditorSlot(options) {
1227
1431
  }
1228
1432
  }
1229
1433
  ),
1230
- condition.operator === "not_empty" ? null : /* @__PURE__ */ jsx13(
1434
+ condition.operator === "not_empty" ? null : /* @__PURE__ */ jsx14(
1231
1435
  TextInput,
1232
1436
  {
1233
1437
  id: `mui-field-${field.id}-condition-value`,
@@ -1239,11 +1443,11 @@ function createMuiFieldEditorSlot(options) {
1239
1443
  )
1240
1444
  ] })
1241
1445
  ] }),
1242
- currentLocale.length === 0 ? null : /* @__PURE__ */ jsxs7(Stack3, { spacing: resolved.dense ? 1 : 2, children: [
1243
- /* @__PURE__ */ jsx13(Typography3, { variant: "subtitle2", children: translate("builder.translation", {
1446
+ currentLocale.length === 0 ? null : /* @__PURE__ */ jsxs8(Stack4, { spacing: resolved.dense ? 1 : 2, children: [
1447
+ /* @__PURE__ */ jsx14(Typography3, { variant: "subtitle2", children: translate("builder.translation", {
1244
1448
  locale: resolved.getLocaleLabel?.(currentLocale) ?? currentLocale
1245
1449
  }) }),
1246
- controls.title === "hidden" ? null : /* @__PURE__ */ jsx13(
1450
+ controls.title === "hidden" ? null : /* @__PURE__ */ jsx14(
1247
1451
  TextInput,
1248
1452
  {
1249
1453
  id: `mui-field-${field.id}-${currentLocale}-title`,
@@ -1253,7 +1457,7 @@ function createMuiFieldEditorSlot(options) {
1253
1457
  onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
1254
1458
  }
1255
1459
  ),
1256
- controls.description === "hidden" ? null : /* @__PURE__ */ jsx13(
1460
+ controls.description === "hidden" ? null : /* @__PURE__ */ jsx14(
1257
1461
  TextArea,
1258
1462
  {
1259
1463
  id: `mui-field-${field.id}-${currentLocale}-description`,
@@ -1265,9 +1469,9 @@ function createMuiFieldEditorSlot(options) {
1265
1469
  }
1266
1470
  )
1267
1471
  ] }),
1268
- "options" in field && controls.options !== "hidden" ? /* @__PURE__ */ jsxs7(Stack3, { "data-mui-slot": "options", spacing: resolved.dense ? 1 : 2, children: [
1269
- /* @__PURE__ */ jsx13(Typography3, { variant: "subtitle2", children: translate("builder.options") }),
1270
- field.options.map((option, optionIndex) => /* @__PURE__ */ jsx13(
1472
+ "options" in field && controls.options !== "hidden" ? /* @__PURE__ */ jsxs8(Stack4, { "data-mui-slot": "options", spacing: resolved.dense ? 1 : 2, children: [
1473
+ /* @__PURE__ */ jsx14(Typography3, { variant: "subtitle2", children: translate("builder.options") }),
1474
+ field.options.map((option, optionIndex) => /* @__PURE__ */ jsx14(
1271
1475
  OptionEditor,
1272
1476
  {
1273
1477
  schema,
@@ -1282,8 +1486,8 @@ function createMuiFieldEditorSlot(options) {
1282
1486
  },
1283
1487
  option.id
1284
1488
  )),
1285
- /* @__PURE__ */ jsx13(
1286
- Button2,
1489
+ /* @__PURE__ */ jsx14(
1490
+ Button4,
1287
1491
  {
1288
1492
  action: "addOption",
1289
1493
  targetId: field.id,
@@ -1310,13 +1514,13 @@ import {
1310
1514
  Alert as Alert2,
1311
1515
  Box as Box3,
1312
1516
  Chip,
1313
- Stack as Stack4,
1517
+ Stack as Stack5,
1314
1518
  Tab,
1315
1519
  Tabs,
1316
1520
  Typography as Typography4
1317
1521
  } from "@mui/material";
1318
1522
  import { useEffect, useState } from "react";
1319
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1523
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1320
1524
  var DEFAULT_EMPTY_STATE_MESSAGE = "No translation locales have been added yet. Select a language from the dropdown above to add one.";
1321
1525
  function normalizeLocaleOptions(options, getLocaleLabel) {
1322
1526
  const seen = /* @__PURE__ */ new Set();
@@ -1345,7 +1549,7 @@ function createMuiLocalizationSlot(options) {
1345
1549
  translate
1346
1550
  }) {
1347
1551
  const resolved = useResolvedMuiAdapterOptions(options);
1348
- const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
1552
+ const { Button: Button4, ErrorMessage, Select: Select3, TextArea, TextInput } = components;
1349
1553
  const [newLocale, setNewLocale] = useState("");
1350
1554
  const [pendingFocusLocale, setPendingFocusLocale] = useState(null);
1351
1555
  const locales = Array.from(
@@ -1410,12 +1614,12 @@ function createMuiLocalizationSlot(options) {
1410
1614
  supportedLocales: schema.supportedLocales ?? [],
1411
1615
  totalLocales: registeredLocales.size
1412
1616
  };
1413
- const summary = localizationOptions.renderSummary === void 0 ? localizationOptions.showSummary ? configuredTranslationLocales.length > 0 ? /* @__PURE__ */ jsx14(Alert2, { severity: "success", sx: { mb: 2 }, children: translate("builder.localization.localesConfiguredSummary", {
1617
+ const summary = localizationOptions.renderSummary === void 0 ? localizationOptions.showSummary ? configuredTranslationLocales.length > 0 ? /* @__PURE__ */ jsx15(Alert2, { severity: "success", sx: { mb: 2 }, children: translate("builder.localization.localesConfiguredSummary", {
1414
1618
  count: schema.supportedLocales?.length ?? 0
1415
- }) }) : /* @__PURE__ */ jsx14(Alert2, { severity: "info", sx: { mb: 2 }, children: translate("builder.localization.noLocalesConfigured") }) : null : localizationOptions.renderSummary(summaryContext);
1416
- const title = /* @__PURE__ */ jsxs8(Stack4, { alignItems: "center", direction: "row", spacing: 1, children: [
1417
- /* @__PURE__ */ jsx14(Typography4, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }),
1418
- localizationOptions.renderSummary === void 0 && localizationOptions.showSummary && configuredTranslationLocales.length > 0 ? /* @__PURE__ */ jsx14(
1619
+ }) }) : /* @__PURE__ */ jsx15(Alert2, { severity: "info", sx: { mb: 2 }, children: translate("builder.localization.noLocalesConfigured") }) : null : localizationOptions.renderSummary(summaryContext);
1620
+ const title = /* @__PURE__ */ jsxs9(Stack5, { alignItems: "center", direction: "row", spacing: 1, children: [
1621
+ /* @__PURE__ */ jsx15(Typography4, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }),
1622
+ localizationOptions.renderSummary === void 0 && localizationOptions.showSummary && configuredTranslationLocales.length > 0 ? /* @__PURE__ */ jsx15(
1419
1623
  Chip,
1420
1624
  {
1421
1625
  label: legacySummaryLabel,
@@ -1427,11 +1631,11 @@ function createMuiLocalizationSlot(options) {
1427
1631
  ] });
1428
1632
  const noCandidateLocales = hasLocaleSelector && filteredAvailableLocales.length === 0;
1429
1633
  const candidateHelperText = localeLimitReached ? void 0 : noCandidateLocales ? translate("builder.localization.allLocalesAdded") : void 0;
1430
- const content = /* @__PURE__ */ jsxs8(Stack4, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1634
+ const content = /* @__PURE__ */ jsxs9(Stack5, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1431
1635
  !collapsible ? title : null,
1432
1636
  summary,
1433
- /* @__PURE__ */ jsxs8(
1434
- Stack4,
1637
+ /* @__PURE__ */ jsxs9(
1638
+ Stack5,
1435
1639
  {
1436
1640
  ...stackProps,
1437
1641
  direction: { xs: "column", sm: "row" },
@@ -1439,16 +1643,16 @@ function createMuiLocalizationSlot(options) {
1439
1643
  spacing: resolved.dense ? 1 : 2,
1440
1644
  sx: { mt: 1 },
1441
1645
  children: [
1442
- defaultLocaleControl === "hidden" ? null : /* @__PURE__ */ jsx14(Box3, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, children: defaultLocaleControl === "readOnly" ? /* @__PURE__ */ jsxs8(Stack4, { spacing: 0.5, children: [
1443
- /* @__PURE__ */ jsx14(Typography4, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
1444
- /* @__PURE__ */ jsx14(
1646
+ defaultLocaleControl === "hidden" ? null : /* @__PURE__ */ jsx15(Box3, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, children: defaultLocaleControl === "readOnly" ? /* @__PURE__ */ jsxs9(Stack5, { spacing: 0.5, children: [
1647
+ /* @__PURE__ */ jsx15(Typography4, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
1648
+ /* @__PURE__ */ jsx15(
1445
1649
  Chip,
1446
1650
  {
1447
1651
  label: resolved.getLocaleLabel?.(schema.defaultLocale ?? "") ?? schema.defaultLocale ?? "",
1448
1652
  size: resolved.size
1449
1653
  }
1450
1654
  )
1451
- ] }) : /* @__PURE__ */ jsx14(
1655
+ ] }) : /* @__PURE__ */ jsx15(
1452
1656
  TextInput,
1453
1657
  {
1454
1658
  id: "mui-builder-default-locale",
@@ -1461,8 +1665,8 @@ function createMuiLocalizationSlot(options) {
1461
1665
  }
1462
1666
  }
1463
1667
  ) }),
1464
- /* @__PURE__ */ jsx14(Box3, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, onKeyDownCapture: handleAddKeyDown, children: hasLocaleSelector ? /* @__PURE__ */ jsx14(
1465
- Select2,
1668
+ /* @__PURE__ */ jsx15(Box3, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, onKeyDownCapture: handleAddKeyDown, children: hasLocaleSelector ? /* @__PURE__ */ jsx15(
1669
+ Select3,
1466
1670
  {
1467
1671
  id: "mui-builder-new-locale",
1468
1672
  label: translate("builder.localization.selectLocaleToAdd"),
@@ -1472,7 +1676,7 @@ function createMuiLocalizationSlot(options) {
1472
1676
  disabled: readOnly || localeLimitReached || noCandidateLocales,
1473
1677
  onChange: setNewLocale
1474
1678
  }
1475
- ) : /* @__PURE__ */ jsx14(
1679
+ ) : /* @__PURE__ */ jsx15(
1476
1680
  TextInput,
1477
1681
  {
1478
1682
  id: "mui-builder-new-locale",
@@ -1482,7 +1686,7 @@ function createMuiLocalizationSlot(options) {
1482
1686
  onChange: setNewLocale
1483
1687
  }
1484
1688
  ) }),
1485
- /* @__PURE__ */ jsx14(
1689
+ /* @__PURE__ */ jsx15(
1486
1690
  Box3,
1487
1691
  {
1488
1692
  sx: {
@@ -1490,8 +1694,8 @@ function createMuiLocalizationSlot(options) {
1490
1694
  minWidth: "max-content",
1491
1695
  ...localizationOptions.noWrapActions ?? true ? { whiteSpace: "nowrap" } : {}
1492
1696
  },
1493
- children: /* @__PURE__ */ jsx14(
1494
- Button2,
1697
+ children: /* @__PURE__ */ jsx15(
1698
+ Button4,
1495
1699
  {
1496
1700
  variant: "primary",
1497
1701
  action: "addLocale",
@@ -1506,8 +1710,8 @@ function createMuiLocalizationSlot(options) {
1506
1710
  ]
1507
1711
  }
1508
1712
  ),
1509
- localeLimitReached ? /* @__PURE__ */ jsx14(Typography4, { variant: "body2", color: "text.secondary", children: translate("builder.localization.maxLocalesReached", { max: policy?.maxLocales ?? 0 }) }) : null,
1510
- locales.length === 0 ? null : /* @__PURE__ */ jsx14(
1713
+ localeLimitReached ? /* @__PURE__ */ jsx15(Typography4, { variant: "body2", color: "text.secondary", children: translate("builder.localization.maxLocalesReached", { max: policy?.maxLocales ?? 0 }) }) : null,
1714
+ locales.length === 0 ? null : /* @__PURE__ */ jsx15(
1511
1715
  Tabs,
1512
1716
  {
1513
1717
  value: editingLocaleConfigured ? currentLocale : false,
@@ -1515,7 +1719,7 @@ function createMuiLocalizationSlot(options) {
1515
1719
  variant: "scrollable",
1516
1720
  scrollButtons: "auto",
1517
1721
  "aria-label": translate("builder.translationLocale"),
1518
- children: locales.map((locale) => /* @__PURE__ */ jsx14(
1722
+ children: locales.map((locale) => /* @__PURE__ */ jsx15(
1519
1723
  Tab,
1520
1724
  {
1521
1725
  id: `mui-builder-locale-tab-${locale}`,
@@ -1528,8 +1732,8 @@ function createMuiLocalizationSlot(options) {
1528
1732
  ))
1529
1733
  }
1530
1734
  ),
1531
- !translationAdapterAvailable ? null : /* @__PURE__ */ jsx14(Box3, { sx: { minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx14(
1532
- Button2,
1735
+ !translationAdapterAvailable ? null : /* @__PURE__ */ jsx15(Box3, { sx: { minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx15(
1736
+ Button4,
1533
1737
  {
1534
1738
  variant: "secondary",
1535
1739
  noWrap: localizationOptions.noWrapActions ?? true,
@@ -1538,9 +1742,9 @@ function createMuiLocalizationSlot(options) {
1538
1742
  children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
1539
1743
  }
1540
1744
  ) }),
1541
- translationError === void 0 ? null : /* @__PURE__ */ jsx14(ErrorMessage, { message: translationError }),
1542
- !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: [
1543
- /* @__PURE__ */ jsx14(
1745
+ translationError === void 0 ? null : /* @__PURE__ */ jsx15(ErrorMessage, { message: translationError }),
1746
+ !editingLocaleConfigured ? /* @__PURE__ */ jsx15(Typography4, { variant: "body2", color: "text.secondary", children: locales.length === 0 ? emptyStateMessage : translate("builder.selectLocale") }) : /* @__PURE__ */ jsxs9(Stack5, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1747
+ /* @__PURE__ */ jsx15(
1544
1748
  TextInput,
1545
1749
  {
1546
1750
  id: `mui-builder-${currentLocale}-form-title`,
@@ -1550,7 +1754,7 @@ function createMuiLocalizationSlot(options) {
1550
1754
  onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "title", value)
1551
1755
  }
1552
1756
  ),
1553
- /* @__PURE__ */ jsx14(
1757
+ /* @__PURE__ */ jsx15(
1554
1758
  TextArea,
1555
1759
  {
1556
1760
  id: `mui-builder-${currentLocale}-form-description`,
@@ -1560,7 +1764,7 @@ function createMuiLocalizationSlot(options) {
1560
1764
  onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "description", value)
1561
1765
  }
1562
1766
  ),
1563
- /* @__PURE__ */ jsx14(
1767
+ /* @__PURE__ */ jsx15(
1564
1768
  TextInput,
1565
1769
  {
1566
1770
  id: `mui-builder-${currentLocale}-completion-message`,
@@ -1575,12 +1779,12 @@ function createMuiLocalizationSlot(options) {
1575
1779
  const configured = locales.length > 0;
1576
1780
  const defaultExpanded = localizationOptions.defaultExpanded === "when-configured" ? configured : localizationOptions.defaultExpanded === "always" ? true : localizationOptions.defaultExpanded ?? false;
1577
1781
  if (collapsible) {
1578
- return /* @__PURE__ */ jsxs8(Accordion, { ...resolved.muiSlotProps?.accordion, "data-mui-slot": "localization", defaultExpanded, children: [
1579
- /* @__PURE__ */ jsx14(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx14(ExpandMore, {}), children: title }),
1580
- /* @__PURE__ */ jsx14(AccordionDetails, { children: content })
1782
+ return /* @__PURE__ */ jsxs9(Accordion, { ...resolved.muiSlotProps?.accordion, "data-mui-slot": "localization", defaultExpanded, children: [
1783
+ /* @__PURE__ */ jsx15(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx15(ExpandMore, {}), children: title }),
1784
+ /* @__PURE__ */ jsx15(AccordionDetails, { children: content })
1581
1785
  ] });
1582
1786
  }
1583
- return /* @__PURE__ */ jsx14(
1787
+ return /* @__PURE__ */ jsx15(
1584
1788
  Box3,
1585
1789
  {
1586
1790
  "data-mui-slot": "localization",
@@ -1599,8 +1803,8 @@ function createMuiLocalizationSlot(options) {
1599
1803
  var MuiLocalizationSlot = createMuiLocalizationSlot();
1600
1804
 
1601
1805
  // src/slots/MuiChoiceGroupSlot.tsx
1602
- import { FormControl as FormControl3, FormHelperText as FormHelperText3, FormLabel, Paper as Paper2 } from "@mui/material";
1603
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1806
+ import { FormControl as FormControl4, FormHelperText as FormHelperText3, FormLabel, Paper as Paper2 } from "@mui/material";
1807
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1604
1808
  function MuiChoiceGroupSlot({
1605
1809
  title,
1606
1810
  description,
@@ -1610,7 +1814,7 @@ function MuiChoiceGroupSlot({
1610
1814
  children,
1611
1815
  className
1612
1816
  }) {
1613
- return /* @__PURE__ */ jsx15(
1817
+ return /* @__PURE__ */ jsx16(
1614
1818
  Paper2,
1615
1819
  {
1616
1820
  className,
@@ -1621,11 +1825,11 @@ function MuiChoiceGroupSlot({
1621
1825
  mb: 2,
1622
1826
  p: 2
1623
1827
  },
1624
- children: /* @__PURE__ */ jsxs9(FormControl3, { component: "fieldset", error: error !== void 0, fullWidth: true, required, disabled, children: [
1625
- /* @__PURE__ */ jsx15(FormLabel, { component: "legend", sx: { fontWeight: "bold", mb: description === void 0 ? 1 : 0.5 }, children: title }),
1626
- description === void 0 ? null : /* @__PURE__ */ jsx15(FormHelperText3, { sx: { mt: 0, mb: 1 }, children: description }),
1828
+ children: /* @__PURE__ */ jsxs10(FormControl4, { component: "fieldset", error: error !== void 0, fullWidth: true, required, disabled, children: [
1829
+ /* @__PURE__ */ jsx16(FormLabel, { component: "legend", sx: { fontWeight: "bold", mb: description === void 0 ? 1 : 0.5 }, children: title }),
1830
+ description === void 0 ? null : /* @__PURE__ */ jsx16(FormHelperText3, { sx: { mt: 0, mb: 1 }, children: description }),
1627
1831
  children,
1628
- error === void 0 ? null : /* @__PURE__ */ jsx15(FormHelperText3, { error: true, children: error.message })
1832
+ error === void 0 ? null : /* @__PURE__ */ jsx16(FormHelperText3, { error: true, children: error.message })
1629
1833
  ] })
1630
1834
  }
1631
1835
  );
@@ -1664,11 +1868,12 @@ import {
1664
1868
  FormBuilder
1665
1869
  } from "@form-engine-ts/react";
1666
1870
  import { useMemo } from "react";
1667
- import { jsx as jsx16 } from "react/jsx-runtime";
1871
+ import { jsx as jsx17 } from "react/jsx-runtime";
1668
1872
  function MuiFormBuilder({
1669
1873
  muiOptions,
1670
1874
  layoutOptions,
1671
1875
  localizationOptions,
1876
+ submissionSettingsOptions,
1672
1877
  muiSlotProps,
1673
1878
  components: customComponents,
1674
1879
  slots: customSlots,
@@ -1687,19 +1892,180 @@ function MuiFormBuilder({
1687
1892
  const components = useMemo(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
1688
1893
  const slots = useMemo(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
1689
1894
  const placement = contextOptions.localizationOptions?.placement;
1690
- const resolvedSectionOrder = sectionOrder ?? (placement === void 0 ? contextOptions.layoutOptions?.sectionOrder : MUI_LOCALIZATION_SECTION_ORDERS[placement]);
1691
- return /* @__PURE__ */ jsx16(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx16(
1895
+ const baseSectionOrder = sectionOrder ?? (placement === void 0 ? contextOptions.layoutOptions?.sectionOrder : MUI_LOCALIZATION_SECTION_ORDERS[placement]);
1896
+ const resolvedSectionOrder = (() => {
1897
+ if (submissionSettingsOptions?.enabled !== true) return baseSectionOrder;
1898
+ const order = [
1899
+ ...baseSectionOrder ?? DEFAULT_MUI_SECTION_ORDER
1900
+ ].filter((name) => name !== "submissionSettings");
1901
+ const settingsPlacement = submissionSettingsOptions.placement ?? "bottom";
1902
+ const target = settingsPlacement === "beforeQuestions" ? "questions" : settingsPlacement === "afterQuestions" ? "addQuestion" : void 0;
1903
+ if (target === void 0) return [...order, "submissionSettings"];
1904
+ const index = order.indexOf(target);
1905
+ order.splice(
1906
+ index < 0 ? order.length : index + (settingsPlacement === "afterQuestions" ? 1 : 0),
1907
+ 0,
1908
+ "submissionSettings"
1909
+ );
1910
+ return order;
1911
+ })();
1912
+ return /* @__PURE__ */ jsx17(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx17(
1692
1913
  FormBuilder,
1693
1914
  {
1694
1915
  ...props,
1695
1916
  components,
1696
1917
  disableDefaultStyles: true,
1697
1918
  slots,
1698
- ...resolvedSectionOrder === void 0 ? {} : { sectionOrder: resolvedSectionOrder }
1919
+ ...resolvedSectionOrder === void 0 ? {} : { sectionOrder: resolvedSectionOrder },
1920
+ ...submissionSettingsOptions === void 0 ? {} : { submissionSettingsOptions }
1699
1921
  }
1700
1922
  ) });
1701
1923
  }
1924
+
1925
+ // src/workspace/TranslationWorkspace.tsx
1926
+ import { useTranslationWorkspace } from "@form-engine-ts/react";
1927
+ import {
1928
+ Button as Button3,
1929
+ Card as Card2,
1930
+ CardContent,
1931
+ Chip as Chip2,
1932
+ LinearProgress,
1933
+ Stack as Stack6,
1934
+ Tab as Tab2,
1935
+ Tabs as Tabs2,
1936
+ TextField as TextField4,
1937
+ Typography as Typography5
1938
+ } from "@mui/material";
1939
+ import { useState as useState2 } from "react";
1940
+ import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
1941
+ var statusLabel = {
1942
+ missing: "Missing",
1943
+ translated: "Translated",
1944
+ stale: "Source changed",
1945
+ manual: "Manual",
1946
+ "manual-stale": "Manual / source changed"
1947
+ };
1948
+ function SlotCard({
1949
+ slot,
1950
+ readOnly,
1951
+ onChange,
1952
+ onTranslate
1953
+ }) {
1954
+ return /* @__PURE__ */ jsx18(Card2, { variant: "outlined", children: /* @__PURE__ */ jsx18(CardContent, { children: /* @__PURE__ */ jsxs11(Stack6, { spacing: 1.5, children: [
1955
+ /* @__PURE__ */ jsxs11(Stack6, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [
1956
+ /* @__PURE__ */ jsx18(Typography5, { variant: "subtitle2", children: slot.path }),
1957
+ /* @__PURE__ */ jsx18(Chip2, { size: "small", label: statusLabel[slot.status ?? "missing"] })
1958
+ ] }),
1959
+ /* @__PURE__ */ jsx18(
1960
+ TextField4,
1961
+ {
1962
+ label: "Source",
1963
+ value: slot.sourceText,
1964
+ multiline: true,
1965
+ fullWidth: true,
1966
+ slotProps: { input: { readOnly: true } }
1967
+ }
1968
+ ),
1969
+ /* @__PURE__ */ jsx18(
1970
+ TextField4,
1971
+ {
1972
+ label: "Translation",
1973
+ value: slot.existingText ?? "",
1974
+ multiline: true,
1975
+ fullWidth: true,
1976
+ disabled: readOnly,
1977
+ onChange: (event) => onChange(event.target.value)
1978
+ }
1979
+ ),
1980
+ slot.status === "stale" || slot.status === "manual-stale" ? /* @__PURE__ */ jsx18(Typography5, { color: "warning.main", variant: "body2", children: "The source text has changed since this translation was created." }) : null,
1981
+ /* @__PURE__ */ jsx18(Button3, { variant: "outlined", onClick: onTranslate, disabled: readOnly, children: "Translate this slot" })
1982
+ ] }) }) });
1983
+ }
1984
+ function TranslationWorkspace({
1985
+ schema,
1986
+ onChange,
1987
+ sourceLocale,
1988
+ targetLocale,
1989
+ translationAdapter,
1990
+ readOnly = false
1991
+ }) {
1992
+ const workspace = useTranslationWorkspace({
1993
+ schema,
1994
+ ...onChange === void 0 ? {} : { onChange },
1995
+ ...sourceLocale === void 0 ? {} : { sourceLocale },
1996
+ ...targetLocale === void 0 ? {} : { targetLocale },
1997
+ ...translationAdapter === void 0 ? {} : { translationAdapter },
1998
+ readOnly
1999
+ });
2000
+ const [newLocale, setNewLocale] = useState2("");
2001
+ return /* @__PURE__ */ jsxs11(Stack6, { spacing: 2, "data-testid": "translation-workspace", children: [
2002
+ /* @__PURE__ */ jsxs11(Stack6, { direction: { xs: "column", sm: "row" }, spacing: 2, alignItems: { sm: "center" }, children: [
2003
+ /* @__PURE__ */ jsx18(Typography5, { variant: "h6", children: "Translations" }),
2004
+ /* @__PURE__ */ jsxs11(Typography5, { variant: "body2", children: [
2005
+ workspace.summary.completionPercentage,
2006
+ "% complete (",
2007
+ workspace.summary.translatedCount,
2008
+ "/",
2009
+ workspace.summary.totalSlots,
2010
+ ")"
2011
+ ] }),
2012
+ /* @__PURE__ */ jsx18(
2013
+ Button3,
2014
+ {
2015
+ variant: "contained",
2016
+ onClick: () => void workspace.translateAll(),
2017
+ disabled: readOnly || workspace.isTranslating,
2018
+ children: "Translate all"
2019
+ }
2020
+ )
2021
+ ] }),
2022
+ /* @__PURE__ */ jsx18(LinearProgress, { variant: "determinate", value: workspace.summary.completionPercentage }),
2023
+ /* @__PURE__ */ jsxs11(Stack6, { direction: "row", spacing: 1, alignItems: "center", children: [
2024
+ /* @__PURE__ */ jsx18(
2025
+ Tabs2,
2026
+ {
2027
+ value: workspace.targetLocale,
2028
+ onChange: (_event, value) => workspace.setTargetLocale(value),
2029
+ "aria-label": "Translation locales",
2030
+ children: workspace.targetLocales.map((locale) => /* @__PURE__ */ jsx18(Tab2, { value: locale, label: locale }, locale))
2031
+ }
2032
+ ),
2033
+ /* @__PURE__ */ jsx18(
2034
+ TextField4,
2035
+ {
2036
+ size: "small",
2037
+ label: "Add locale",
2038
+ value: newLocale,
2039
+ onChange: (event) => setNewLocale(event.target.value)
2040
+ }
2041
+ ),
2042
+ /* @__PURE__ */ jsx18(
2043
+ Button3,
2044
+ {
2045
+ onClick: () => {
2046
+ workspace.addLocale(newLocale);
2047
+ setNewLocale("");
2048
+ },
2049
+ disabled: readOnly,
2050
+ children: "Add"
2051
+ }
2052
+ )
2053
+ ] }),
2054
+ workspace.error === void 0 ? null : /* @__PURE__ */ jsx18(Typography5, { color: "error", children: workspace.error }),
2055
+ /* @__PURE__ */ jsx18(Stack6, { spacing: 1.5, children: workspace.slots.map((slot) => /* @__PURE__ */ jsx18(
2056
+ SlotCard,
2057
+ {
2058
+ slot,
2059
+ readOnly,
2060
+ onChange: (text) => workspace.setTranslation(slot, text),
2061
+ onTranslate: () => void workspace.translateSlot(slot)
2062
+ },
2063
+ slot.path
2064
+ )) })
2065
+ ] });
2066
+ }
1702
2067
  export {
2068
+ ConditionEditor,
1703
2069
  DEFAULT_MUI_SECTION_ORDER,
1704
2070
  MUI_LOCALIZATION_SECTION_ORDERS,
1705
2071
  MuiButtonAdapter,
@@ -1718,6 +2084,7 @@ export {
1718
2084
  MuiTextAreaAdapter,
1719
2085
  MuiTextInputAdapter,
1720
2086
  MuiToolbarSlot,
2087
+ TranslationWorkspace,
1721
2088
  createMuiBuilderComponents,
1722
2089
  createMuiBuilderProps,
1723
2090
  createMuiBuilderSlots,