@form-engine-ts/mui 4.3.2 → 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.cjs CHANGED
@@ -20,10 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ ConditionEditor: () => ConditionEditor,
23
24
  DEFAULT_MUI_SECTION_ORDER: () => DEFAULT_MUI_SECTION_ORDER,
24
25
  MUI_LOCALIZATION_SECTION_ORDERS: () => MUI_LOCALIZATION_SECTION_ORDERS,
25
26
  MuiButtonAdapter: () => MuiButtonAdapter,
26
27
  MuiCheckboxAdapter: () => MuiCheckboxAdapter,
28
+ MuiChoiceGroupSlot: () => MuiChoiceGroupSlot,
27
29
  MuiErrorMessageAdapter: () => MuiErrorMessageAdapter,
28
30
  MuiFieldEditorSlot: () => MuiFieldEditorSlot,
29
31
  MuiFieldsetAdapter: () => MuiFieldsetAdapter,
@@ -37,6 +39,7 @@ __export(index_exports, {
37
39
  MuiTextAreaAdapter: () => MuiTextAreaAdapter,
38
40
  MuiTextInputAdapter: () => MuiTextInputAdapter,
39
41
  MuiToolbarSlot: () => MuiToolbarSlot,
42
+ TranslationWorkspace: () => TranslationWorkspace,
40
43
  createMuiBuilderComponents: () => createMuiBuilderComponents,
41
44
  createMuiBuilderProps: () => createMuiBuilderProps,
42
45
  createMuiBuilderSlots: () => createMuiBuilderSlots,
@@ -791,11 +794,189 @@ function createMuiBuilderComponents(optionsOrOverrides = {}, customOverrides) {
791
794
  // src/slots/FieldEditor.tsx
792
795
  var import_core = require("@form-engine-ts/core");
793
796
  var import_react2 = require("@form-engine-ts/react");
794
- var import_material12 = require("@mui/material");
797
+ var import_material13 = require("@mui/material");
795
798
 
796
- // src/slots/OptionEditor.tsx
799
+ // src/slots/ConditionEditor.tsx
797
800
  var import_material10 = require("@mui/material");
798
801
  var import_jsx_runtime11 = require("react/jsx-runtime");
802
+ var OPERATORS = [
803
+ "equals",
804
+ "not_equals",
805
+ "contains",
806
+ "not_contains",
807
+ "is_empty",
808
+ "is_not_empty",
809
+ "greater_than",
810
+ "less_than"
811
+ ];
812
+ function sourceIds(field) {
813
+ if (field.displayRule === void 0)
814
+ return field.displayCondition?.questionId === void 0 ? [] : [field.displayCondition.questionId];
815
+ const ids = [];
816
+ const visit = (group) => {
817
+ for (const condition of group.conditions) {
818
+ if ("logic" in condition) visit(condition);
819
+ else ids.push(condition.fieldId);
820
+ }
821
+ };
822
+ visit(field.displayRule.condition);
823
+ return ids;
824
+ }
825
+ function dependsOn(schema, startId, targetId, visited = /* @__PURE__ */ new Set()) {
826
+ if (startId === targetId) return true;
827
+ if (visited.has(startId)) return false;
828
+ visited.add(startId);
829
+ const field = schema.fields.find((candidate) => candidate.id === startId);
830
+ return field !== void 0 && sourceIds(field).some((sourceId) => dependsOn(schema, sourceId, targetId, visited));
831
+ }
832
+ function operatorsFor(field) {
833
+ if (field === void 0) return [];
834
+ if (field.type === "checkbox" || field.type === "multi-select")
835
+ return ["contains", "not_contains", "is_empty", "is_not_empty"];
836
+ if (field.type === "text" || field.type === "textarea")
837
+ return OPERATORS.filter(
838
+ (operator) => ["equals", "not_equals", "contains", "not_contains", "is_empty", "is_not_empty"].includes(operator)
839
+ );
840
+ if (field.type === "number" || field.type === "rating")
841
+ return ["equals", "not_equals", "greater_than", "less_than", "is_empty", "is_not_empty"];
842
+ return ["equals", "not_equals", "is_empty", "is_not_empty"];
843
+ }
844
+ function conditionGroup(rule) {
845
+ return rule?.condition ?? { logic: "all", conditions: [] };
846
+ }
847
+ function conditionValue(field, condition, onChange) {
848
+ if (["is_empty", "is_not_empty"].includes(condition.operator)) return null;
849
+ if (field !== void 0 && "options" in field) {
850
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.FormControl, { fullWidth: true, size: "small", children: [
851
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.InputLabel, { children: "Value" }),
852
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.Select, { label: "Value", value: String(condition.value ?? ""), onChange: (event) => onChange(event.target.value), children: field.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.MenuItem, { value: option.id, children: option.label }, option.id)) })
853
+ ] });
854
+ }
855
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
856
+ import_material10.TextField,
857
+ {
858
+ label: "Value",
859
+ type: field?.type === "number" || field?.type === "rating" ? "number" : "text",
860
+ value: condition.value === void 0 ? "" : String(condition.value),
861
+ onChange: (event) => onChange(field?.type === "number" || field?.type === "rating" ? Number(event.target.value) : event.target.value),
862
+ fullWidth: true,
863
+ size: "small"
864
+ }
865
+ );
866
+ }
867
+ function ConditionEditor({ schema, fieldId, value, onChange, readOnly = false }) {
868
+ const group = conditionGroup(value);
869
+ const candidates = schema.fields.filter((field) => field.id !== fieldId && !dependsOn(schema, field.id, fieldId));
870
+ const updateGroup = (nextGroup) => onChange({ action: value?.action ?? "show", condition: nextGroup });
871
+ const updateCondition = (index, nextCondition) => {
872
+ const conditions = group.conditions.map(
873
+ (condition, conditionIndex) => conditionIndex === index ? nextCondition : condition
874
+ );
875
+ updateGroup({ ...group, conditions });
876
+ };
877
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.Stack, { spacing: 1.5, "data-testid": `condition-editor-${fieldId}`, children: [
878
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
879
+ import_material10.ToggleButtonGroup,
880
+ {
881
+ exclusive: true,
882
+ value: group.logic,
883
+ onChange: (_event, logic) => logic === null ? void 0 : updateGroup({ ...group, logic }),
884
+ disabled: readOnly,
885
+ size: "small",
886
+ children: [
887
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.ToggleButton, { value: "all", children: "All (AND)" }),
888
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.ToggleButton, { value: "any", children: "Any (OR)" })
889
+ ]
890
+ }
891
+ ),
892
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.FormControl, { fullWidth: true, size: "small", children: [
893
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.InputLabel, { children: "Action" }),
894
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
895
+ import_material10.Select,
896
+ {
897
+ label: "Action",
898
+ value: value?.action ?? "show",
899
+ onChange: (event) => onChange({ action: event.target.value, condition: group }),
900
+ disabled: readOnly,
901
+ children: [
902
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.MenuItem, { value: "show", children: "Show when matched" }),
903
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.MenuItem, { value: "hide", children: "Hide when matched" })
904
+ ]
905
+ }
906
+ )
907
+ ] }),
908
+ group.conditions.map((condition, index) => {
909
+ if ("logic" in condition) return null;
910
+ const source = schema.fields.find((field) => field.id === condition.fieldId);
911
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.Stack, { direction: { xs: "column", md: "row" }, spacing: 1, children: [
912
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.FormControl, { fullWidth: true, size: "small", children: [
913
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.InputLabel, { children: "Question" }),
914
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
915
+ import_material10.Select,
916
+ {
917
+ label: "Question",
918
+ value: condition.fieldId,
919
+ onChange: (event) => {
920
+ const nextSource = schema.fields.find((field) => field.id === event.target.value);
921
+ const nextOperator = operatorsFor(nextSource)[0] ?? "equals";
922
+ updateCondition(index, { fieldId: event.target.value, operator: nextOperator });
923
+ },
924
+ disabled: readOnly,
925
+ children: candidates.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.MenuItem, { value: candidate.id, children: candidate.title }, candidate.id))
926
+ }
927
+ )
928
+ ] }),
929
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.FormControl, { fullWidth: true, size: "small", children: [
930
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.InputLabel, { children: "Operator" }),
931
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
932
+ import_material10.Select,
933
+ {
934
+ label: "Operator",
935
+ value: condition.operator,
936
+ onChange: (event) => updateCondition(index, { ...condition, operator: event.target.value }),
937
+ disabled: readOnly,
938
+ children: operatorsFor(source).map((operator) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material10.MenuItem, { value: operator, children: operator }, operator))
939
+ }
940
+ )
941
+ ] }),
942
+ conditionValue(
943
+ source,
944
+ condition,
945
+ (nextValue) => updateCondition(index, { ...condition, value: nextValue })
946
+ ),
947
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
948
+ import_material10.Button,
949
+ {
950
+ onClick: () => updateGroup({
951
+ ...group,
952
+ conditions: group.conditions.filter((_item, itemIndex) => itemIndex !== index)
953
+ }),
954
+ disabled: readOnly,
955
+ children: "Remove"
956
+ }
957
+ )
958
+ ] }, `${condition.fieldId}-${condition.operator}`);
959
+ }),
960
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
961
+ import_material10.Button,
962
+ {
963
+ variant: "outlined",
964
+ disabled: readOnly || candidates.length === 0,
965
+ onClick: () => {
966
+ const source = candidates[0];
967
+ if (source === void 0) return;
968
+ const operator = operatorsFor(source)[0] ?? "equals";
969
+ updateGroup({ ...group, conditions: [...group.conditions, { fieldId: source.id, operator }] });
970
+ },
971
+ children: "Add condition"
972
+ }
973
+ )
974
+ ] });
975
+ }
976
+
977
+ // src/slots/OptionEditor.tsx
978
+ var import_material11 = require("@mui/material");
979
+ var import_jsx_runtime12 = require("react/jsx-runtime");
799
980
  function createMuiOptionEditorSlot(options) {
800
981
  return function MuiOptionEditor({
801
982
  field,
@@ -810,9 +991,9 @@ function createMuiOptionEditorSlot(options) {
810
991
  const resolved = useResolvedMuiAdapterOptions(options);
811
992
  const { IconButton: IconButton2, TextInput } = components;
812
993
  const describedBy = option.label.trim().length === 0 ? `mui-option-${option.id}-error` : void 0;
813
- 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: [
814
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, alignItems: { sm: "flex-start" }, children: [
815
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
994
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material11.Stack, { ...resolved.muiSlotProps?.stack, "data-mui-slot": "option-editor", spacing: resolved.dense ? 0.75 : 1, children: [
995
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material11.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, alignItems: { sm: "flex-start" }, children: [
996
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
816
997
  TextInput,
817
998
  {
818
999
  id: `mui-option-${option.id}`,
@@ -826,8 +1007,8 @@ function createMuiOptionEditorSlot(options) {
826
1007
  onChange: (value) => actions.updateOption(field.id, option.id, (current) => ({ ...current, label: value }))
827
1008
  }
828
1009
  ),
829
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.Stack, { direction: "row", spacing: 0.5, children: [
830
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1010
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material11.Stack, { direction: "row", spacing: 0.5, children: [
1011
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
831
1012
  IconButton2,
832
1013
  {
833
1014
  actionType: "moveUp",
@@ -836,7 +1017,7 @@ function createMuiOptionEditorSlot(options) {
836
1017
  onClick: () => actions.moveOption(field.id, option.id, index - 1)
837
1018
  }
838
1019
  ),
839
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1020
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
840
1021
  IconButton2,
841
1022
  {
842
1023
  actionType: "moveDown",
@@ -845,7 +1026,7 @@ function createMuiOptionEditorSlot(options) {
845
1026
  onClick: () => actions.moveOption(field.id, option.id, index + 1)
846
1027
  }
847
1028
  ),
848
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1029
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
849
1030
  IconButton2,
850
1031
  {
851
1032
  actionType: "delete",
@@ -856,7 +1037,7 @@ function createMuiOptionEditorSlot(options) {
856
1037
  )
857
1038
  ] })
858
1039
  ] }),
859
- currentLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1040
+ currentLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
860
1041
  TextInput,
861
1042
  {
862
1043
  id: `mui-option-${option.id}-${currentLocale}`,
@@ -874,8 +1055,8 @@ function createMuiOptionEditorSlot(options) {
874
1055
  var MuiOptionEditorSlot = createMuiOptionEditorSlot();
875
1056
 
876
1057
  // src/slots/Toolbar.tsx
877
- var import_material11 = require("@mui/material");
878
- var import_jsx_runtime12 = require("react/jsx-runtime");
1058
+ var import_material12 = require("@mui/material");
1059
+ var import_jsx_runtime13 = require("react/jsx-runtime");
879
1060
  function createMuiToolbarSlot(options) {
880
1061
  return function MuiToolbar({
881
1062
  kind,
@@ -891,8 +1072,8 @@ function createMuiToolbarSlot(options) {
891
1072
  }) {
892
1073
  const resolved = useResolvedMuiAdapterOptions(options);
893
1074
  const { IconButton: IconButton2 } = components;
894
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
895
- import_material11.Stack,
1075
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1076
+ import_material12.Stack,
896
1077
  {
897
1078
  ...resolved.muiSlotProps?.stack,
898
1079
  "data-mui-slot": "toolbar",
@@ -901,7 +1082,7 @@ function createMuiToolbarSlot(options) {
901
1082
  alignItems: "center",
902
1083
  sx: resolved.muiSlotProps?.stack?.sx ?? { mb: resolved.dense ? 1 : 2 },
903
1084
  children: [
904
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1085
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
905
1086
  IconButton2,
906
1087
  {
907
1088
  actionType: "moveUp",
@@ -910,7 +1091,7 @@ function createMuiToolbarSlot(options) {
910
1091
  onClick: onMoveUp
911
1092
  }
912
1093
  ),
913
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1094
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
914
1095
  IconButton2,
915
1096
  {
916
1097
  actionType: "moveDown",
@@ -919,7 +1100,7 @@ function createMuiToolbarSlot(options) {
919
1100
  onClick: onMoveDown
920
1101
  }
921
1102
  ),
922
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1103
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
923
1104
  IconButton2,
924
1105
  {
925
1106
  actionType: "delete",
@@ -936,7 +1117,7 @@ function createMuiToolbarSlot(options) {
936
1117
  var MuiToolbarSlot = createMuiToolbarSlot();
937
1118
 
938
1119
  // src/slots/FieldEditor.tsx
939
- var import_jsx_runtime13 = require("react/jsx-runtime");
1120
+ var import_jsx_runtime14 = require("react/jsx-runtime");
940
1121
  var FIELD_TYPES = import_core.DEFAULT_FIELD_TYPE_DEFINITIONS.map((definition) => definition.type);
941
1122
  function isFieldType(value) {
942
1123
  return FIELD_TYPES.some((type) => type === value);
@@ -989,7 +1170,7 @@ function createMuiFieldEditorSlot(options) {
989
1170
  fieldTypeOptions: fieldTypeOptionsConfig
990
1171
  }) {
991
1172
  const resolved = useResolvedMuiAdapterOptions(options);
992
- const { Button: Button2, Checkbox: Checkbox2, Select: Select2, TextArea, TextInput } = components;
1173
+ const { Button: Button4, Checkbox: Checkbox2, Select: Select3, TextArea, TextInput } = components;
993
1174
  const allowedTypes = policy?.allowedFieldTypes ?? FIELD_TYPES;
994
1175
  const pageId = schema.pages?.find((page) => page.questionIds.includes(field.id))?.id ?? "";
995
1176
  const condition = field.displayCondition;
@@ -1033,16 +1214,16 @@ function createMuiFieldEditorSlot(options) {
1033
1214
  const changeFieldType = (nextType) => {
1034
1215
  if (allowedTypes.includes(nextType)) actions.changeFieldType(field.id, nextType);
1035
1216
  };
1036
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1037
- import_material12.Card,
1217
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1218
+ import_material13.Card,
1038
1219
  {
1039
1220
  ...resolved.muiSlotProps?.card,
1040
1221
  "data-mui-slot": "field-editor",
1041
1222
  variant: "outlined",
1042
1223
  sx: resolved.muiSlotProps?.card?.sx ?? { mb: resolved.dense ? 1 : 2, p: resolved.dense ? 1.5 : 2 },
1043
1224
  children: [
1044
- FieldEditorHeader === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1045
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1225
+ FieldEditorHeader === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1226
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1046
1227
  Toolbar,
1047
1228
  {
1048
1229
  schema,
@@ -1060,11 +1241,11 @@ function createMuiFieldEditorSlot(options) {
1060
1241
  components
1061
1242
  }
1062
1243
  ),
1063
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material12.Typography, { variant: "subtitle1", fontWeight: "bold", children: field.title })
1064
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FieldEditorHeader, { field, index, totalFields: schema.fields.length, actions }),
1065
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { ...resolved.muiSlotProps?.stack, spacing: resolved.dense ? 1 : 2, children: [
1066
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1067
- controls.title === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1244
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "subtitle1", fontWeight: "bold", children: field.title })
1245
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FieldEditorHeader, { field, index, totalFields: schema.fields.length, actions }),
1246
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...resolved.muiSlotProps?.stack, spacing: resolved.dense ? 1 : 2, children: [
1247
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1248
+ controls.title === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1068
1249
  TextInput,
1069
1250
  {
1070
1251
  id: `mui-field-${field.id}-title`,
@@ -1079,8 +1260,8 @@ function createMuiFieldEditorSlot(options) {
1079
1260
  onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "title", value)
1080
1261
  }
1081
1262
  ),
1082
- controls.typeSelect === "hidden" ? null : FieldTypeSelect === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1083
- Select2,
1263
+ controls.typeSelect === "hidden" ? null : FieldTypeSelect === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1264
+ Select3,
1084
1265
  {
1085
1266
  id: fieldTypeSelectId,
1086
1267
  name: `fields.${field.id}.type`,
@@ -1092,7 +1273,7 @@ function createMuiFieldEditorSlot(options) {
1092
1273
  if (isFieldType(value)) changeFieldType(value);
1093
1274
  }
1094
1275
  }
1095
- ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1276
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1096
1277
  FieldTypeSelect,
1097
1278
  {
1098
1279
  id: fieldTypeSelectId,
@@ -1109,7 +1290,7 @@ function createMuiFieldEditorSlot(options) {
1109
1290
  }
1110
1291
  )
1111
1292
  ] }),
1112
- controls.description === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1293
+ controls.description === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1113
1294
  TextArea,
1114
1295
  {
1115
1296
  id: `mui-field-${field.id}-description`,
@@ -1122,7 +1303,7 @@ function createMuiFieldEditorSlot(options) {
1122
1303
  onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "description", value)
1123
1304
  }
1124
1305
  ),
1125
- controls.required === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1306
+ controls.required === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1126
1307
  Checkbox2,
1127
1308
  {
1128
1309
  id: `mui-field-${field.id}-required`,
@@ -1133,8 +1314,8 @@ function createMuiFieldEditorSlot(options) {
1133
1314
  onChange: (checked) => actions.updateField(field.id, (current) => ({ ...current, required: checked }))
1134
1315
  }
1135
1316
  ),
1136
- features?.pages === false || schema.pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1137
- Select2,
1317
+ features?.pages === false || schema.pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1318
+ Select3,
1138
1319
  {
1139
1320
  id: `mui-field-${field.id}-page`,
1140
1321
  label: translate("builder.questionPage"),
@@ -1147,8 +1328,8 @@ function createMuiFieldEditorSlot(options) {
1147
1328
  onChange: (value) => actions.assignFieldToPage(field.id, value.length === 0 ? null : value)
1148
1329
  }
1149
1330
  ),
1150
- field.type === "number" || field.type === "rating" ? (field.type === "number" ? controls.numberLimits : controls.ratingBounds) === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1151
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1331
+ field.type === "number" || field.type === "rating" ? (field.type === "number" ? controls.numberLimits : controls.ratingBounds) === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1332
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1152
1333
  TextInput,
1153
1334
  {
1154
1335
  id: `mui-field-${field.id}-minimum`,
@@ -1159,7 +1340,7 @@ function createMuiFieldEditorSlot(options) {
1159
1340
  onChange: (value) => actions.updateField(field.id, (current) => updateBound(current, "min", value))
1160
1341
  }
1161
1342
  ),
1162
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1343
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1163
1344
  TextInput,
1164
1345
  {
1165
1346
  id: `mui-field-${field.id}-maximum`,
@@ -1171,7 +1352,7 @@ function createMuiFieldEditorSlot(options) {
1171
1352
  }
1172
1353
  )
1173
1354
  ] }) : null,
1174
- field.type === "number" && controls.numberLimits !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1355
+ field.type === "number" && controls.numberLimits !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1175
1356
  TextInput,
1176
1357
  {
1177
1358
  id: `mui-field-${field.id}-step`,
@@ -1182,8 +1363,8 @@ function createMuiFieldEditorSlot(options) {
1182
1363
  onChange: (value) => actions.updateField(field.id, (current) => updateNumberProperty(current, "step", value))
1183
1364
  }
1184
1365
  ) : null,
1185
- (field.type === "text" || field.type === "textarea") && controls.textLimits !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1186
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1366
+ (field.type === "text" || field.type === "textarea") && controls.textLimits !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1367
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1187
1368
  TextInput,
1188
1369
  {
1189
1370
  id: `mui-field-${field.id}-min-length`,
@@ -1198,7 +1379,7 @@ function createMuiFieldEditorSlot(options) {
1198
1379
  })
1199
1380
  }
1200
1381
  ),
1201
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1382
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1202
1383
  TextInput,
1203
1384
  {
1204
1385
  id: `mui-field-${field.id}-max-length`,
@@ -1213,7 +1394,7 @@ function createMuiFieldEditorSlot(options) {
1213
1394
  })
1214
1395
  }
1215
1396
  ),
1216
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1397
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1217
1398
  TextInput,
1218
1399
  {
1219
1400
  id: `mui-field-${field.id}-pattern`,
@@ -1227,9 +1408,25 @@ function createMuiFieldEditorSlot(options) {
1227
1408
  }
1228
1409
  )
1229
1410
  ] }) : null,
1230
- features?.conditions === false || conditionSources.length === 0 || controls.displayConditions === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1231
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1232
- Select2,
1411
+ features?.conditions === false || conditionSources.length === 0 || controls.displayConditions === "hidden" ? null : field.displayRule !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1412
+ ConditionEditor,
1413
+ {
1414
+ schema,
1415
+ fieldId: field.id,
1416
+ value: field.displayRule,
1417
+ readOnly: readOnly || controls.displayConditions === "readOnly",
1418
+ onChange: (displayRule) => actions.updateField(field.id, (current) => {
1419
+ const { displayCondition: _displayCondition, ...withoutLegacyCondition } = current;
1420
+ if (displayRule === void 0) {
1421
+ const { displayRule: _displayRule, ...withoutRules } = withoutLegacyCondition;
1422
+ return withoutRules;
1423
+ }
1424
+ return { ...withoutLegacyCondition, displayRule };
1425
+ })
1426
+ }
1427
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1428
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1429
+ Select3,
1233
1430
  {
1234
1431
  id: `mui-field-${field.id}-condition-source`,
1235
1432
  label: translate("builder.displayCondition"),
@@ -1245,9 +1442,9 @@ function createMuiFieldEditorSlot(options) {
1245
1442
  )
1246
1443
  }
1247
1444
  ),
1248
- condition === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1249
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1250
- Select2,
1445
+ condition === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1446
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1447
+ Select3,
1251
1448
  {
1252
1449
  id: `mui-field-${field.id}-condition-operator`,
1253
1450
  label: translate("builder.conditionOperator"),
@@ -1265,7 +1462,7 @@ function createMuiFieldEditorSlot(options) {
1265
1462
  }
1266
1463
  }
1267
1464
  ),
1268
- condition.operator === "not_empty" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1465
+ condition.operator === "not_empty" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1269
1466
  TextInput,
1270
1467
  {
1271
1468
  id: `mui-field-${field.id}-condition-value`,
@@ -1277,11 +1474,11 @@ function createMuiFieldEditorSlot(options) {
1277
1474
  )
1278
1475
  ] })
1279
1476
  ] }),
1280
- currentLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { spacing: resolved.dense ? 1 : 2, children: [
1281
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material12.Typography, { variant: "subtitle2", children: translate("builder.translation", {
1477
+ currentLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { spacing: resolved.dense ? 1 : 2, children: [
1478
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "subtitle2", children: translate("builder.translation", {
1282
1479
  locale: resolved.getLocaleLabel?.(currentLocale) ?? currentLocale
1283
1480
  }) }),
1284
- controls.title === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1481
+ controls.title === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1285
1482
  TextInput,
1286
1483
  {
1287
1484
  id: `mui-field-${field.id}-${currentLocale}-title`,
@@ -1291,7 +1488,7 @@ function createMuiFieldEditorSlot(options) {
1291
1488
  onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
1292
1489
  }
1293
1490
  ),
1294
- controls.description === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1491
+ controls.description === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1295
1492
  TextArea,
1296
1493
  {
1297
1494
  id: `mui-field-${field.id}-${currentLocale}-description`,
@@ -1303,9 +1500,9 @@ function createMuiFieldEditorSlot(options) {
1303
1500
  }
1304
1501
  )
1305
1502
  ] }),
1306
- "options" in field && controls.options !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { "data-mui-slot": "options", spacing: resolved.dense ? 1 : 2, children: [
1307
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material12.Typography, { variant: "subtitle2", children: translate("builder.options") }),
1308
- field.options.map((option, optionIndex) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1503
+ "options" in field && controls.options !== "hidden" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { "data-mui-slot": "options", spacing: resolved.dense ? 1 : 2, children: [
1504
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "subtitle2", children: translate("builder.options") }),
1505
+ field.options.map((option, optionIndex) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1309
1506
  OptionEditor,
1310
1507
  {
1311
1508
  schema,
@@ -1320,8 +1517,8 @@ function createMuiFieldEditorSlot(options) {
1320
1517
  },
1321
1518
  option.id
1322
1519
  )),
1323
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1324
- Button2,
1520
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1521
+ Button4,
1325
1522
  {
1326
1523
  action: "addOption",
1327
1524
  targetId: field.id,
@@ -1341,9 +1538,9 @@ var MuiFieldEditorSlot = createMuiFieldEditorSlot();
1341
1538
 
1342
1539
  // src/slots/Localization.tsx
1343
1540
  var import_icons_material2 = require("@mui/icons-material");
1344
- var import_material13 = require("@mui/material");
1541
+ var import_material14 = require("@mui/material");
1345
1542
  var import_react3 = require("react");
1346
- var import_jsx_runtime14 = require("react/jsx-runtime");
1543
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1347
1544
  var DEFAULT_EMPTY_STATE_MESSAGE = "No translation locales have been added yet. Select a language from the dropdown above to add one.";
1348
1545
  function normalizeLocaleOptions(options, getLocaleLabel) {
1349
1546
  const seen = /* @__PURE__ */ new Set();
@@ -1372,7 +1569,7 @@ function createMuiLocalizationSlot(options) {
1372
1569
  translate
1373
1570
  }) {
1374
1571
  const resolved = useResolvedMuiAdapterOptions(options);
1375
- const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
1572
+ const { Button: Button4, ErrorMessage, Select: Select3, TextArea, TextInput } = components;
1376
1573
  const [newLocale, setNewLocale] = (0, import_react3.useState)("");
1377
1574
  const [pendingFocusLocale, setPendingFocusLocale] = (0, import_react3.useState)(null);
1378
1575
  const locales = Array.from(
@@ -1437,13 +1634,13 @@ function createMuiLocalizationSlot(options) {
1437
1634
  supportedLocales: schema.supportedLocales ?? [],
1438
1635
  totalLocales: registeredLocales.size
1439
1636
  };
1440
- const summary = localizationOptions.renderSummary === void 0 ? localizationOptions.showSummary ? configuredTranslationLocales.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Alert, { severity: "success", sx: { mb: 2 }, children: translate("builder.localization.localesConfiguredSummary", {
1637
+ const summary = localizationOptions.renderSummary === void 0 ? localizationOptions.showSummary ? configuredTranslationLocales.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Alert, { severity: "success", sx: { mb: 2 }, children: translate("builder.localization.localesConfiguredSummary", {
1441
1638
  count: schema.supportedLocales?.length ?? 0
1442
- }) }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Alert, { severity: "info", sx: { mb: 2 }, children: translate("builder.localization.noLocalesConfigured") }) : null : localizationOptions.renderSummary(summaryContext);
1443
- const title = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { alignItems: "center", direction: "row", spacing: 1, children: [
1444
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }),
1445
- localizationOptions.renderSummary === void 0 && localizationOptions.showSummary && configuredTranslationLocales.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1446
- import_material13.Chip,
1639
+ }) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Alert, { severity: "info", sx: { mb: 2 }, children: translate("builder.localization.noLocalesConfigured") }) : null : localizationOptions.renderSummary(summaryContext);
1640
+ const title = /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_material14.Stack, { alignItems: "center", direction: "row", spacing: 1, children: [
1641
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Typography, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }),
1642
+ localizationOptions.renderSummary === void 0 && localizationOptions.showSummary && configuredTranslationLocales.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1643
+ import_material14.Chip,
1447
1644
  {
1448
1645
  label: legacySummaryLabel,
1449
1646
  size: "small",
@@ -1454,11 +1651,11 @@ function createMuiLocalizationSlot(options) {
1454
1651
  ] });
1455
1652
  const noCandidateLocales = hasLocaleSelector && filteredAvailableLocales.length === 0;
1456
1653
  const candidateHelperText = localeLimitReached ? void 0 : noCandidateLocales ? translate("builder.localization.allLocalesAdded") : void 0;
1457
- const content = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1654
+ const content = /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_material14.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1458
1655
  !collapsible ? title : null,
1459
1656
  summary,
1460
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1461
- import_material13.Stack,
1657
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1658
+ import_material14.Stack,
1462
1659
  {
1463
1660
  ...stackProps,
1464
1661
  direction: { xs: "column", sm: "row" },
@@ -1466,16 +1663,16 @@ function createMuiLocalizationSlot(options) {
1466
1663
  spacing: resolved.dense ? 1 : 2,
1467
1664
  sx: { mt: 1 },
1468
1665
  children: [
1469
- defaultLocaleControl === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Box, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, children: defaultLocaleControl === "readOnly" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { spacing: 0.5, children: [
1470
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
1471
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1472
- import_material13.Chip,
1666
+ defaultLocaleControl === "hidden" ? null : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Box, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, children: defaultLocaleControl === "readOnly" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_material14.Stack, { spacing: 0.5, children: [
1667
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Typography, { variant: "caption", color: "text.secondary", children: translate("builder.defaultLocale") }),
1668
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1669
+ import_material14.Chip,
1473
1670
  {
1474
1671
  label: resolved.getLocaleLabel?.(schema.defaultLocale ?? "") ?? schema.defaultLocale ?? "",
1475
1672
  size: resolved.size
1476
1673
  }
1477
1674
  )
1478
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1675
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1479
1676
  TextInput,
1480
1677
  {
1481
1678
  id: "mui-builder-default-locale",
@@ -1488,8 +1685,8 @@ function createMuiLocalizationSlot(options) {
1488
1685
  }
1489
1686
  }
1490
1687
  ) }),
1491
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Box, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, onKeyDownCapture: handleAddKeyDown, children: hasLocaleSelector ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1492
- Select2,
1688
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Box, { sx: { flexGrow: 1, minWidth: 0, width: { xs: "100%", sm: "auto" } }, onKeyDownCapture: handleAddKeyDown, children: hasLocaleSelector ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1689
+ Select3,
1493
1690
  {
1494
1691
  id: "mui-builder-new-locale",
1495
1692
  label: translate("builder.localization.selectLocaleToAdd"),
@@ -1499,7 +1696,7 @@ function createMuiLocalizationSlot(options) {
1499
1696
  disabled: readOnly || localeLimitReached || noCandidateLocales,
1500
1697
  onChange: setNewLocale
1501
1698
  }
1502
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1699
+ ) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1503
1700
  TextInput,
1504
1701
  {
1505
1702
  id: "mui-builder-new-locale",
@@ -1509,16 +1706,16 @@ function createMuiLocalizationSlot(options) {
1509
1706
  onChange: setNewLocale
1510
1707
  }
1511
1708
  ) }),
1512
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1513
- import_material13.Box,
1709
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1710
+ import_material14.Box,
1514
1711
  {
1515
1712
  sx: {
1516
1713
  flexShrink: 0,
1517
1714
  minWidth: "max-content",
1518
1715
  ...localizationOptions.noWrapActions ?? true ? { whiteSpace: "nowrap" } : {}
1519
1716
  },
1520
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1521
- Button2,
1717
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1718
+ Button4,
1522
1719
  {
1523
1720
  variant: "primary",
1524
1721
  action: "addLocale",
@@ -1533,17 +1730,17 @@ function createMuiLocalizationSlot(options) {
1533
1730
  ]
1534
1731
  }
1535
1732
  ),
1536
- localeLimitReached ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "body2", color: "text.secondary", children: translate("builder.localization.maxLocalesReached", { max: policy?.maxLocales ?? 0 }) }) : null,
1537
- locales.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1538
- import_material13.Tabs,
1733
+ localeLimitReached ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Typography, { variant: "body2", color: "text.secondary", children: translate("builder.localization.maxLocalesReached", { max: policy?.maxLocales ?? 0 }) }) : null,
1734
+ locales.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1735
+ import_material14.Tabs,
1539
1736
  {
1540
1737
  value: editingLocaleConfigured ? currentLocale : false,
1541
1738
  onChange: handleTabChange,
1542
1739
  variant: "scrollable",
1543
1740
  scrollButtons: "auto",
1544
1741
  "aria-label": translate("builder.translationLocale"),
1545
- children: locales.map((locale) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1546
- import_material13.Tab,
1742
+ children: locales.map((locale) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1743
+ import_material14.Tab,
1547
1744
  {
1548
1745
  id: `mui-builder-locale-tab-${locale}`,
1549
1746
  value: locale,
@@ -1555,8 +1752,8 @@ function createMuiLocalizationSlot(options) {
1555
1752
  ))
1556
1753
  }
1557
1754
  ),
1558
- !translationAdapterAvailable ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Box, { sx: { minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1559
- Button2,
1755
+ !translationAdapterAvailable ? null : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Box, { sx: { minWidth: "max-content", whiteSpace: "nowrap" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1756
+ Button4,
1560
1757
  {
1561
1758
  variant: "secondary",
1562
1759
  noWrap: localizationOptions.noWrapActions ?? true,
@@ -1565,9 +1762,9 @@ function createMuiLocalizationSlot(options) {
1565
1762
  children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
1566
1763
  }
1567
1764
  ) }),
1568
- translationError === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ErrorMessage, { message: translationError }),
1569
- !editingLocaleConfigured ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "body2", color: "text.secondary", children: locales.length === 0 ? emptyStateMessage : translate("builder.selectLocale") }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1570
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1765
+ translationError === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ErrorMessage, { message: translationError }),
1766
+ !editingLocaleConfigured ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.Typography, { variant: "body2", color: "text.secondary", children: locales.length === 0 ? emptyStateMessage : translate("builder.selectLocale") }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_material14.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1767
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1571
1768
  TextInput,
1572
1769
  {
1573
1770
  id: `mui-builder-${currentLocale}-form-title`,
@@ -1577,7 +1774,7 @@ function createMuiLocalizationSlot(options) {
1577
1774
  onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "title", value)
1578
1775
  }
1579
1776
  ),
1580
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1777
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1581
1778
  TextArea,
1582
1779
  {
1583
1780
  id: `mui-builder-${currentLocale}-form-description`,
@@ -1587,7 +1784,7 @@ function createMuiLocalizationSlot(options) {
1587
1784
  onChange: (value) => actions.setManualTranslation(currentLocale, { kind: "form" }, "description", value)
1588
1785
  }
1589
1786
  ),
1590
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1787
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1591
1788
  TextInput,
1592
1789
  {
1593
1790
  id: `mui-builder-${currentLocale}-completion-message`,
@@ -1602,13 +1799,13 @@ function createMuiLocalizationSlot(options) {
1602
1799
  const configured = locales.length > 0;
1603
1800
  const defaultExpanded = localizationOptions.defaultExpanded === "when-configured" ? configured : localizationOptions.defaultExpanded === "always" ? true : localizationOptions.defaultExpanded ?? false;
1604
1801
  if (collapsible) {
1605
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Accordion, { ...resolved.muiSlotProps?.accordion, "data-mui-slot": "localization", defaultExpanded, children: [
1606
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.AccordionSummary, { expandIcon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_material2.ExpandMore, {}), children: title }),
1607
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.AccordionDetails, { children: content })
1802
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_material14.Accordion, { ...resolved.muiSlotProps?.accordion, "data-mui-slot": "localization", defaultExpanded, children: [
1803
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.AccordionSummary, { expandIcon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons_material2.ExpandMore, {}), children: title }),
1804
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material14.AccordionDetails, { children: content })
1608
1805
  ] });
1609
1806
  }
1610
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1611
- import_material13.Box,
1807
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1808
+ import_material14.Box,
1612
1809
  {
1613
1810
  "data-mui-slot": "localization",
1614
1811
  sx: {
@@ -1625,6 +1822,39 @@ function createMuiLocalizationSlot(options) {
1625
1822
  }
1626
1823
  var MuiLocalizationSlot = createMuiLocalizationSlot();
1627
1824
 
1825
+ // src/slots/MuiChoiceGroupSlot.tsx
1826
+ var import_material15 = require("@mui/material");
1827
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1828
+ function MuiChoiceGroupSlot({
1829
+ title,
1830
+ description,
1831
+ required,
1832
+ error,
1833
+ disabled,
1834
+ children,
1835
+ className
1836
+ }) {
1837
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1838
+ import_material15.Paper,
1839
+ {
1840
+ className,
1841
+ variant: "outlined",
1842
+ sx: {
1843
+ borderColor: error === void 0 ? "divider" : "error.main",
1844
+ borderRadius: 2,
1845
+ mb: 2,
1846
+ p: 2
1847
+ },
1848
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_material15.FormControl, { component: "fieldset", error: error !== void 0, fullWidth: true, required, disabled, children: [
1849
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_material15.FormLabel, { component: "legend", sx: { fontWeight: "bold", mb: description === void 0 ? 1 : 0.5 }, children: title }),
1850
+ description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_material15.FormHelperText, { sx: { mt: 0, mb: 1 }, children: description }),
1851
+ children,
1852
+ error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_material15.FormHelperText, { error: true, children: error.message })
1853
+ ] })
1854
+ }
1855
+ );
1856
+ }
1857
+
1628
1858
  // src/slots/index.ts
1629
1859
  var muiBuilderSlots = {
1630
1860
  sectionOrder: DEFAULT_MUI_SECTION_ORDER,
@@ -1656,11 +1886,12 @@ function createMuiBuilderProps(options, overrides = {}) {
1656
1886
  // src/MuiFormBuilder.tsx
1657
1887
  var import_react4 = require("@form-engine-ts/react");
1658
1888
  var import_react5 = require("react");
1659
- var import_jsx_runtime15 = require("react/jsx-runtime");
1889
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1660
1890
  function MuiFormBuilder({
1661
1891
  muiOptions,
1662
1892
  layoutOptions,
1663
1893
  localizationOptions,
1894
+ submissionSettingsOptions,
1664
1895
  muiSlotProps,
1665
1896
  components: customComponents,
1666
1897
  slots: customSlots,
@@ -1679,24 +1910,175 @@ function MuiFormBuilder({
1679
1910
  const components = (0, import_react5.useMemo)(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
1680
1911
  const slots = (0, import_react5.useMemo)(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
1681
1912
  const placement = contextOptions.localizationOptions?.placement;
1682
- const resolvedSectionOrder = sectionOrder ?? (placement === void 0 ? contextOptions.layoutOptions?.sectionOrder : MUI_LOCALIZATION_SECTION_ORDERS[placement]);
1683
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1913
+ const baseSectionOrder = sectionOrder ?? (placement === void 0 ? contextOptions.layoutOptions?.sectionOrder : MUI_LOCALIZATION_SECTION_ORDERS[placement]);
1914
+ const resolvedSectionOrder = (() => {
1915
+ if (submissionSettingsOptions?.enabled !== true) return baseSectionOrder;
1916
+ const order = [
1917
+ ...baseSectionOrder ?? DEFAULT_MUI_SECTION_ORDER
1918
+ ].filter((name) => name !== "submissionSettings");
1919
+ const settingsPlacement = submissionSettingsOptions.placement ?? "bottom";
1920
+ const target = settingsPlacement === "beforeQuestions" ? "questions" : settingsPlacement === "afterQuestions" ? "addQuestion" : void 0;
1921
+ if (target === void 0) return [...order, "submissionSettings"];
1922
+ const index = order.indexOf(target);
1923
+ order.splice(
1924
+ index < 0 ? order.length : index + (settingsPlacement === "afterQuestions" ? 1 : 0),
1925
+ 0,
1926
+ "submissionSettings"
1927
+ );
1928
+ return order;
1929
+ })();
1930
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1684
1931
  import_react4.FormBuilder,
1685
1932
  {
1686
1933
  ...props,
1687
1934
  components,
1688
1935
  disableDefaultStyles: true,
1689
1936
  slots,
1690
- ...resolvedSectionOrder === void 0 ? {} : { sectionOrder: resolvedSectionOrder }
1937
+ ...resolvedSectionOrder === void 0 ? {} : { sectionOrder: resolvedSectionOrder },
1938
+ ...submissionSettingsOptions === void 0 ? {} : { submissionSettingsOptions }
1691
1939
  }
1692
1940
  ) });
1693
1941
  }
1942
+
1943
+ // src/workspace/TranslationWorkspace.tsx
1944
+ var import_react6 = require("@form-engine-ts/react");
1945
+ var import_material16 = require("@mui/material");
1946
+ var import_react7 = require("react");
1947
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1948
+ var statusLabel = {
1949
+ missing: "Missing",
1950
+ translated: "Translated",
1951
+ stale: "Source changed",
1952
+ manual: "Manual",
1953
+ "manual-stale": "Manual / source changed"
1954
+ };
1955
+ function SlotCard({
1956
+ slot,
1957
+ readOnly,
1958
+ onChange,
1959
+ onTranslate
1960
+ }) {
1961
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Card, { variant: "outlined", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { spacing: 1.5, children: [
1962
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [
1963
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { variant: "subtitle2", children: slot.path }),
1964
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Chip, { size: "small", label: statusLabel[slot.status ?? "missing"] })
1965
+ ] }),
1966
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1967
+ import_material16.TextField,
1968
+ {
1969
+ label: "Source",
1970
+ value: slot.sourceText,
1971
+ multiline: true,
1972
+ fullWidth: true,
1973
+ slotProps: { input: { readOnly: true } }
1974
+ }
1975
+ ),
1976
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1977
+ import_material16.TextField,
1978
+ {
1979
+ label: "Translation",
1980
+ value: slot.existingText ?? "",
1981
+ multiline: true,
1982
+ fullWidth: true,
1983
+ disabled: readOnly,
1984
+ onChange: (event) => onChange(event.target.value)
1985
+ }
1986
+ ),
1987
+ slot.status === "stale" || slot.status === "manual-stale" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { color: "warning.main", variant: "body2", children: "The source text has changed since this translation was created." }) : null,
1988
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Button, { variant: "outlined", onClick: onTranslate, disabled: readOnly, children: "Translate this slot" })
1989
+ ] }) }) });
1990
+ }
1991
+ function TranslationWorkspace({
1992
+ schema,
1993
+ onChange,
1994
+ sourceLocale,
1995
+ targetLocale,
1996
+ translationAdapter,
1997
+ readOnly = false
1998
+ }) {
1999
+ const workspace = (0, import_react6.useTranslationWorkspace)({
2000
+ schema,
2001
+ ...onChange === void 0 ? {} : { onChange },
2002
+ ...sourceLocale === void 0 ? {} : { sourceLocale },
2003
+ ...targetLocale === void 0 ? {} : { targetLocale },
2004
+ ...translationAdapter === void 0 ? {} : { translationAdapter },
2005
+ readOnly
2006
+ });
2007
+ const [newLocale, setNewLocale] = (0, import_react7.useState)("");
2008
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { spacing: 2, "data-testid": "translation-workspace", children: [
2009
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { direction: { xs: "column", sm: "row" }, spacing: 2, alignItems: { sm: "center" }, children: [
2010
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { variant: "h6", children: "Translations" }),
2011
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Typography, { variant: "body2", children: [
2012
+ workspace.summary.completionPercentage,
2013
+ "% complete (",
2014
+ workspace.summary.translatedCount,
2015
+ "/",
2016
+ workspace.summary.totalSlots,
2017
+ ")"
2018
+ ] }),
2019
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2020
+ import_material16.Button,
2021
+ {
2022
+ variant: "contained",
2023
+ onClick: () => void workspace.translateAll(),
2024
+ disabled: readOnly || workspace.isTranslating,
2025
+ children: "Translate all"
2026
+ }
2027
+ )
2028
+ ] }),
2029
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.LinearProgress, { variant: "determinate", value: workspace.summary.completionPercentage }),
2030
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { direction: "row", spacing: 1, alignItems: "center", children: [
2031
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2032
+ import_material16.Tabs,
2033
+ {
2034
+ value: workspace.targetLocale,
2035
+ onChange: (_event, value) => workspace.setTargetLocale(value),
2036
+ "aria-label": "Translation locales",
2037
+ children: workspace.targetLocales.map((locale) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Tab, { value: locale, label: locale }, locale))
2038
+ }
2039
+ ),
2040
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2041
+ import_material16.TextField,
2042
+ {
2043
+ size: "small",
2044
+ label: "Add locale",
2045
+ value: newLocale,
2046
+ onChange: (event) => setNewLocale(event.target.value)
2047
+ }
2048
+ ),
2049
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2050
+ import_material16.Button,
2051
+ {
2052
+ onClick: () => {
2053
+ workspace.addLocale(newLocale);
2054
+ setNewLocale("");
2055
+ },
2056
+ disabled: readOnly,
2057
+ children: "Add"
2058
+ }
2059
+ )
2060
+ ] }),
2061
+ workspace.error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { color: "error", children: workspace.error }),
2062
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Stack, { spacing: 1.5, children: workspace.slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2063
+ SlotCard,
2064
+ {
2065
+ slot,
2066
+ readOnly,
2067
+ onChange: (text) => workspace.setTranslation(slot, text),
2068
+ onTranslate: () => void workspace.translateSlot(slot)
2069
+ },
2070
+ slot.path
2071
+ )) })
2072
+ ] });
2073
+ }
1694
2074
  // Annotate the CommonJS export names for ESM import in node:
1695
2075
  0 && (module.exports = {
2076
+ ConditionEditor,
1696
2077
  DEFAULT_MUI_SECTION_ORDER,
1697
2078
  MUI_LOCALIZATION_SECTION_ORDERS,
1698
2079
  MuiButtonAdapter,
1699
2080
  MuiCheckboxAdapter,
2081
+ MuiChoiceGroupSlot,
1700
2082
  MuiErrorMessageAdapter,
1701
2083
  MuiFieldEditorSlot,
1702
2084
  MuiFieldsetAdapter,
@@ -1710,6 +2092,7 @@ function MuiFormBuilder({
1710
2092
  MuiTextAreaAdapter,
1711
2093
  MuiTextInputAdapter,
1712
2094
  MuiToolbarSlot,
2095
+ TranslationWorkspace,
1713
2096
  createMuiBuilderComponents,
1714
2097
  createMuiBuilderProps,
1715
2098
  createMuiBuilderSlots,