@form-engine-ts/react 2.2.0 → 2.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
@@ -515,6 +515,13 @@ function useFormBuilder({
515
515
  const normalized = locale.trim();
516
516
  if (normalized.length === 0)
517
517
  return { success: false, error: { type: "invalid_operation", message: "Locale must not be empty." } };
518
+ if (policy?.allowedLocales !== void 0 && !policy.allowedLocales.includes(normalized)) {
519
+ return { success: false, error: { type: "disallowed_locale", locale: normalized } };
520
+ }
521
+ const allUniqueLocales = (0, import_core.collectSchemaLocales)(schema).allUniqueLocales;
522
+ if (!allUniqueLocales.has(normalized) && policy?.maxLocales !== void 0 && allUniqueLocales.size >= policy.maxLocales) {
523
+ return { success: false, error: { type: "max_locales_exceeded", max: policy.maxLocales } };
524
+ }
518
525
  const error = textPolicyError(text);
519
526
  if (error !== void 0) return error;
520
527
  const supportedLocales = [.../* @__PURE__ */ new Set([...schema.supportedLocales ?? [], normalized])];
@@ -583,7 +590,7 @@ function useFormBuilder({
583
590
  onChange({ ...schema, supportedLocales, fields, ...pages === void 0 ? {} : { pages } });
584
591
  return { success: true };
585
592
  },
586
- [onChange, schema, textPolicyError]
593
+ [onChange, policy?.allowedLocales, policy?.maxLocales, schema, textPolicyError]
587
594
  );
588
595
  const addLocale = (0, import_react.useCallback)(
589
596
  (locale) => {
@@ -593,12 +600,10 @@ function useFormBuilder({
593
600
  if (policy?.allowedLocales !== void 0 && !policy.allowedLocales.includes(normalized)) {
594
601
  return { success: false, error: { type: "disallowed_locale", locale: normalized } };
595
602
  }
596
- const registeredLocales = /* @__PURE__ */ new Set([
597
- ...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
598
- ...schema.supportedLocales ?? []
599
- ]);
600
- if (registeredLocales.has(normalized)) return { success: true };
601
- if (policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales) {
603
+ const allUniqueLocales = (0, import_core.collectSchemaLocales)(schema).allUniqueLocales;
604
+ if ((schema.supportedLocales ?? []).includes(normalized) || schema.defaultLocale === normalized)
605
+ return { success: true };
606
+ if (policy?.maxLocales !== void 0 && !allUniqueLocales.has(normalized) && allUniqueLocales.size >= policy.maxLocales) {
602
607
  return { success: false, error: { type: "max_locales_exceeded", max: policy.maxLocales } };
603
608
  }
604
609
  onChange({
@@ -623,11 +628,8 @@ function useFormBuilder({
623
628
  if (policy?.allowedLocales !== void 0 && !policy.allowedLocales.includes(normalized)) {
624
629
  return { success: false, error: { type: "disallowed_locale", locale: normalized } };
625
630
  }
626
- const registeredLocales = /* @__PURE__ */ new Set([
627
- ...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
628
- ...schema.supportedLocales ?? []
629
- ]);
630
- if (!registeredLocales.has(normalized) && policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales) {
631
+ const allUniqueLocales = (0, import_core.collectSchemaLocales)(schema).allUniqueLocales;
632
+ if (!allUniqueLocales.has(normalized) && policy?.maxLocales !== void 0 && allUniqueLocales.size >= policy.maxLocales) {
631
633
  return { success: false, error: { type: "max_locales_exceeded", max: policy.maxLocales } };
632
634
  }
633
635
  onChange({
@@ -670,6 +672,293 @@ function useFormBuilder({
670
672
 
671
673
  // src/builder.tsx
672
674
  var import_jsx_runtime = require("react/jsx-runtime");
675
+ function DefaultButton({
676
+ id,
677
+ className,
678
+ disabled,
679
+ "aria-label": ariaLabel,
680
+ onClick,
681
+ children,
682
+ title,
683
+ action,
684
+ targetId
685
+ }) {
686
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
687
+ "button",
688
+ {
689
+ id,
690
+ className,
691
+ type: "button",
692
+ disabled,
693
+ "aria-label": ariaLabel,
694
+ title,
695
+ "data-builder-action": action,
696
+ "data-target-id": targetId,
697
+ onClick,
698
+ children
699
+ }
700
+ );
701
+ }
702
+ function DefaultIconButton(props) {
703
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
704
+ DefaultButton,
705
+ {
706
+ ...props.id === void 0 ? {} : { id: props.id },
707
+ ...props.className === void 0 ? {} : { className: props.className },
708
+ ...props.disabled === void 0 ? {} : { disabled: props.disabled },
709
+ "aria-label": props["aria-label"] ?? props.title,
710
+ ...props.onClick === void 0 ? {} : { onClick: props.onClick },
711
+ children: props.icon
712
+ }
713
+ );
714
+ }
715
+ function DefaultTextInput({
716
+ id,
717
+ className,
718
+ disabled,
719
+ readOnly,
720
+ "aria-label": ariaLabel,
721
+ name,
722
+ label,
723
+ required,
724
+ error,
725
+ helperText,
726
+ value,
727
+ onChange,
728
+ placeholder,
729
+ maxLength,
730
+ inputMode,
731
+ type = "text",
732
+ min,
733
+ max,
734
+ step
735
+ }) {
736
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
737
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
738
+ "input",
739
+ {
740
+ id,
741
+ name,
742
+ className,
743
+ disabled,
744
+ readOnly,
745
+ required,
746
+ "aria-label": ariaLabel ?? label,
747
+ "aria-invalid": error === true ? true : void 0,
748
+ type: type === "text" ? void 0 : type,
749
+ inputMode,
750
+ min,
751
+ max,
752
+ step,
753
+ value,
754
+ placeholder,
755
+ maxLength,
756
+ onChange: (event) => onChange(event.currentTarget.value)
757
+ }
758
+ ),
759
+ helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: helperText })
760
+ ] });
761
+ }
762
+ function DefaultTextArea({
763
+ id,
764
+ className,
765
+ disabled,
766
+ readOnly,
767
+ "aria-label": ariaLabel,
768
+ name,
769
+ label,
770
+ required,
771
+ error,
772
+ helperText,
773
+ value,
774
+ onChange,
775
+ rows,
776
+ placeholder,
777
+ maxLength
778
+ }) {
779
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
780
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
781
+ "textarea",
782
+ {
783
+ id,
784
+ name,
785
+ className,
786
+ disabled,
787
+ readOnly,
788
+ required,
789
+ "aria-label": ariaLabel ?? label,
790
+ "aria-invalid": error === true ? true : void 0,
791
+ value,
792
+ rows,
793
+ placeholder,
794
+ maxLength,
795
+ onChange: (event) => onChange(event.currentTarget.value)
796
+ }
797
+ ),
798
+ helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: helperText })
799
+ ] });
800
+ }
801
+ function DefaultSelect({
802
+ id,
803
+ className,
804
+ disabled,
805
+ "aria-label": ariaLabel,
806
+ name,
807
+ label,
808
+ required,
809
+ error,
810
+ helperText,
811
+ value,
812
+ onChange,
813
+ options
814
+ }) {
815
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
816
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
817
+ "select",
818
+ {
819
+ id,
820
+ name,
821
+ className,
822
+ disabled,
823
+ required,
824
+ "aria-label": ariaLabel ?? label,
825
+ "aria-invalid": error === true ? true : void 0,
826
+ value,
827
+ onChange: (event) => onChange(event.currentTarget.value),
828
+ children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value))
829
+ }
830
+ ),
831
+ helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: helperText })
832
+ ] });
833
+ }
834
+ function DefaultCheckbox({
835
+ id,
836
+ className,
837
+ disabled,
838
+ "aria-label": ariaLabel,
839
+ checked,
840
+ onChange,
841
+ label
842
+ }) {
843
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className, children: [
844
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
845
+ "input",
846
+ {
847
+ id,
848
+ type: "checkbox",
849
+ disabled,
850
+ "aria-label": ariaLabel,
851
+ checked,
852
+ onChange: (event) => onChange(event.currentTarget.checked)
853
+ }
854
+ ),
855
+ label
856
+ ] });
857
+ }
858
+ function DefaultSection({
859
+ id,
860
+ className,
861
+ title,
862
+ description,
863
+ headingId,
864
+ "aria-label": ariaLabel,
865
+ onClickCapture,
866
+ children
867
+ }) {
868
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
869
+ "section",
870
+ {
871
+ id,
872
+ className,
873
+ "aria-label": ariaLabel,
874
+ "aria-labelledby": title === void 0 ? void 0 : headingId,
875
+ onClickCapture,
876
+ children: [
877
+ title === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: headingId, children: title }),
878
+ description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: description }),
879
+ children
880
+ ]
881
+ }
882
+ );
883
+ }
884
+ function DefaultFieldset({ className, legend, disabled, children }) {
885
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { className, disabled, children: [
886
+ legend === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("legend", { children: legend }),
887
+ children
888
+ ] });
889
+ }
890
+ function DefaultErrorMessage({ message }) {
891
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "form-engine-builder__error", children: message });
892
+ }
893
+ var DEFAULT_COMPONENTS = {
894
+ Button: DefaultButton,
895
+ IconButton: DefaultIconButton,
896
+ TextInput: DefaultTextInput,
897
+ TextArea: DefaultTextArea,
898
+ Select: DefaultSelect,
899
+ Checkbox: DefaultCheckbox,
900
+ Section: DefaultSection,
901
+ Fieldset: DefaultFieldset,
902
+ ErrorMessage: DefaultErrorMessage
903
+ };
904
+ var BuilderPrimitiveContext = (0, import_react2.createContext)({
905
+ components: DEFAULT_COMPONENTS,
906
+ readOnly: false
907
+ });
908
+ function BuilderButton(props) {
909
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
910
+ const Component = context.components.Button;
911
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
912
+ }
913
+ function BuilderIconButton(props) {
914
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
915
+ const Component = context.components.IconButton;
916
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
917
+ }
918
+ function BuilderTextInput(props) {
919
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
920
+ const Component = context.components.TextInput;
921
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
922
+ }
923
+ function BuilderTextArea(props) {
924
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
925
+ const Component = context.components.TextArea;
926
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
927
+ }
928
+ function BuilderSelect(props) {
929
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
930
+ const Component = context.components.Select;
931
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
932
+ }
933
+ function BuilderCheckbox(props) {
934
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
935
+ const Component = context.components.Checkbox;
936
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
937
+ }
938
+ function BuilderSection(props) {
939
+ const Component = (0, import_react2.useContext)(BuilderPrimitiveContext).components.Section;
940
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props });
941
+ }
942
+ function BuilderFieldset(props) {
943
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
944
+ const Component = context.components.Fieldset;
945
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true });
946
+ }
947
+ function BuilderErrorMessage(props) {
948
+ const Component = (0, import_react2.useContext)(BuilderPrimitiveContext).components.ErrorMessage;
949
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props });
950
+ }
951
+ var GUARDED_COMPONENTS = {
952
+ Button: BuilderButton,
953
+ IconButton: BuilderIconButton,
954
+ TextInput: BuilderTextInput,
955
+ TextArea: BuilderTextArea,
956
+ Select: BuilderSelect,
957
+ Checkbox: BuilderCheckbox,
958
+ Section: BuilderSection,
959
+ Fieldset: BuilderFieldset,
960
+ ErrorMessage: BuilderErrorMessage
961
+ };
673
962
  var FIELD_TYPES = [
674
963
  "text",
675
964
  "textarea",
@@ -768,37 +1057,52 @@ function ConditionValueEditor({
768
1057
  source,
769
1058
  condition,
770
1059
  onChange,
771
- translate
1060
+ translate,
1061
+ components
772
1062
  }) {
1063
+ const { Select, TextInput } = components;
773
1064
  if (condition.operator === "not_empty") return null;
774
1065
  const update = (value) => onChange({ ...condition, value });
775
1066
  if (source.type === "checkbox") {
776
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: String(condition.value), onChange: (event) => update(event.currentTarget.value === "true"), children: [
777
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "true", children: translate("builder.conditionTrue") }),
778
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "false", children: translate("builder.conditionFalse") })
779
- ] });
1067
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1068
+ Select,
1069
+ {
1070
+ value: String(condition.value),
1071
+ onChange: (value) => update(value === "true"),
1072
+ options: [
1073
+ { value: "true", label: translate("builder.conditionTrue") },
1074
+ { value: "false", label: translate("builder.conditionFalse") }
1075
+ ]
1076
+ }
1077
+ );
780
1078
  }
781
1079
  if (source.type === "number" || source.type === "rating") {
782
1080
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
783
- "input",
1081
+ TextInput,
784
1082
  {
785
1083
  "aria-label": translate("builder.conditionValue"),
786
1084
  type: "number",
787
- value: typeof condition.value === "number" ? condition.value : "",
788
- onChange: (event) => update(event.currentTarget.value === "" ? 0 : event.currentTarget.valueAsNumber)
1085
+ value: typeof condition.value === "number" ? String(condition.value) : "",
1086
+ onChange: (value) => update(value === "" ? 0 : Number(value))
789
1087
  }
790
1088
  );
791
1089
  }
792
1090
  if ("options" in source) {
793
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { value: String(condition.value ?? ""), onChange: (event) => update(event.currentTarget.value), children: source.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: option.id, children: option.label }, option.id)) });
1091
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1092
+ Select,
1093
+ {
1094
+ value: String(condition.value ?? ""),
1095
+ onChange: update,
1096
+ options: source.options.map((option) => ({ value: option.id, label: option.label }))
1097
+ }
1098
+ );
794
1099
  }
795
1100
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
796
- "input",
1101
+ TextInput,
797
1102
  {
798
1103
  "aria-label": translate("builder.conditionValue"),
799
- type: "text",
800
1104
  value: typeof condition.value === "string" ? condition.value : "",
801
- onChange: (event) => update(event.currentTarget.value)
1105
+ onChange: update
802
1106
  }
803
1107
  );
804
1108
  }
@@ -826,8 +1130,19 @@ function FormBuilder({
826
1130
  onActionError,
827
1131
  createManualTranslationMetadata,
828
1132
  readOnly = false,
829
- features
1133
+ features,
1134
+ components: componentOverrides,
1135
+ slots
830
1136
  }) {
1137
+ const resolvedComponents = { ...DEFAULT_COMPONENTS, ...componentOverrides };
1138
+ const components = GUARDED_COMPONENTS;
1139
+ const { Button, Checkbox, ErrorMessage, Fieldset, IconButton, Section, Select, TextInput } = components;
1140
+ const ToolbarSlot = slots?.toolbar;
1141
+ const FieldEditorSlot = slots?.fieldEditor;
1142
+ const OptionEditorSlot = slots?.optionEditor;
1143
+ const PagesSlot = slots?.pages;
1144
+ const LocalizationSlot = slots?.localization;
1145
+ const TranslationActionsSlot = slots?.translationActions;
831
1146
  const headless = useFormBuilder({
832
1147
  schema,
833
1148
  onChange,
@@ -840,6 +1155,7 @@ function FormBuilder({
840
1155
  const [editingLocale, setEditingLocale] = (0, import_react2.useState)("");
841
1156
  const [isTranslating, setIsTranslating] = (0, import_react2.useState)(false);
842
1157
  const [translationError, setTranslationError] = (0, import_react2.useState)(null);
1158
+ const [translationReport, setTranslationReport] = (0, import_react2.useState)();
843
1159
  const translate = (key, params = {}) => {
844
1160
  const translated = translator?.translate(key, locale, params);
845
1161
  return translated === void 0 ? interpolate(BUILDER_DEFAULTS[key] ?? key, params) : translated;
@@ -950,13 +1266,17 @@ function FormBuilder({
950
1266
  setIsTranslating(true);
951
1267
  setTranslationError(null);
952
1268
  try {
1269
+ const translationPolicy = policy ?? translationOptions?.policy;
953
1270
  const populated = await (0, import_core2.populateSchemaTranslations)(schema, [editingLocale], translationAdapter, {
954
1271
  overwrite: "missing-only",
955
- ...translationOptions
1272
+ ...translationOptions,
1273
+ ...translationPolicy === void 0 ? {} : { policy: translationPolicy }
956
1274
  });
957
1275
  onChange(populated.schema);
1276
+ setTranslationReport(populated.report);
958
1277
  onTranslationReport?.(populated.report);
959
1278
  } catch (cause) {
1279
+ setTranslationReport(void 0);
960
1280
  setTranslationError(cause instanceof Error ? cause.message : String(cause));
961
1281
  } finally {
962
1282
  setIsTranslating(false);
@@ -1025,8 +1345,81 @@ function FormBuilder({
1025
1345
  ]);
1026
1346
  const availableAllowedLocales = policy?.allowedLocales?.filter((candidate) => !registeredLocales.has(candidate));
1027
1347
  const localeLimitReached = policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales;
1028
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1029
- "section",
1348
+ const actions = {
1349
+ addField: (type, pageId) => executeAction(() => headless.addField(type, pageId), {
1350
+ action: "addField",
1351
+ ...pageId === void 0 ? { params: { type } } : { targetId: pageId, params: { type, pageId } }
1352
+ }),
1353
+ removeField: (fieldId) => executeAction(() => headless.removeField(fieldId), { action: "removeField", targetId: fieldId }),
1354
+ moveField: (fieldId, targetIndex) => executeAction(() => headless.moveField(fieldId, targetIndex), {
1355
+ action: "moveField",
1356
+ targetId: fieldId,
1357
+ params: { targetIndex }
1358
+ }),
1359
+ updateField: (fieldId, updater) => executeAction(() => headless.updateField(fieldId, updater), { action: "updateField", targetId: fieldId }),
1360
+ changeFieldType: (fieldId, type) => executeAction(() => headless.changeFieldType(fieldId, type), {
1361
+ action: "changeFieldType",
1362
+ targetId: fieldId,
1363
+ params: { type }
1364
+ }),
1365
+ addOption: (fieldId) => executeAction(() => headless.addOption(fieldId), { action: "addOption", targetId: fieldId }),
1366
+ updateOption: (fieldId, optionId, updater) => executeAction(() => headless.updateOption(fieldId, optionId, updater), {
1367
+ action: "updateOption",
1368
+ targetId: optionId,
1369
+ params: { fieldId }
1370
+ }),
1371
+ removeOption: (fieldId, optionId) => executeAction(() => headless.removeOption(fieldId, optionId), {
1372
+ action: "removeOption",
1373
+ targetId: optionId,
1374
+ params: { fieldId }
1375
+ }),
1376
+ moveOption: (fieldId, optionId, targetIndex) => executeAction(() => headless.moveOption(fieldId, optionId, targetIndex), {
1377
+ action: "moveOption",
1378
+ targetId: optionId,
1379
+ params: { fieldId, targetIndex }
1380
+ }),
1381
+ addPage: (questionId) => executeAction(() => headless.addPage(questionId), {
1382
+ action: "addPage",
1383
+ ...questionId === void 0 ? {} : { targetId: questionId, params: { questionId } }
1384
+ }),
1385
+ updatePage: (pageId, updater) => executeAction(() => headless.updatePage(pageId, updater), { action: "updatePage", targetId: pageId }),
1386
+ removePage: (pageId) => executeAction(() => headless.removePage(pageId), { action: "removePage", targetId: pageId }),
1387
+ movePage: (pageId, targetIndex) => executeAction(() => headless.movePage(pageId, targetIndex), {
1388
+ action: "movePage",
1389
+ targetId: pageId,
1390
+ params: { targetIndex }
1391
+ }),
1392
+ assignFieldToPage: (fieldId, pageId) => executeAction(() => headless.assignFieldToPage(fieldId, pageId), {
1393
+ action: "assignFieldToPage",
1394
+ targetId: fieldId,
1395
+ params: { pageId }
1396
+ }),
1397
+ setDisplayCondition: (fieldId, condition) => executeAction(() => headless.setDisplayCondition(fieldId, condition), {
1398
+ action: "setDisplayCondition",
1399
+ targetId: fieldId,
1400
+ ...condition === void 0 ? {} : { params: { condition } }
1401
+ }),
1402
+ setSourceText: (target, property, text) => executeAction(() => headless.setSourceText(target, property, text), {
1403
+ action: "setSourceText",
1404
+ ...target.id === void 0 ? {} : { targetId: target.id },
1405
+ params: { property, text }
1406
+ }),
1407
+ setLocaleTranslation: (targetLocale, target, property, text, options) => executeAction(() => headless.setLocaleTranslation(targetLocale, target, property, text, options), {
1408
+ action: "setLocaleTranslation",
1409
+ ...target.id === void 0 ? {} : { targetId: target.id },
1410
+ params: { locale: targetLocale, property }
1411
+ }),
1412
+ addLocale: (targetLocale) => executeAction(() => headless.addLocale(targetLocale), {
1413
+ action: "addLocale",
1414
+ params: { locale: targetLocale }
1415
+ }),
1416
+ setDefaultLocale: (targetLocale) => executeAction(() => headless.setDefaultLocale(targetLocale), {
1417
+ action: "setDefaultLocale",
1418
+ params: { locale: targetLocale }
1419
+ })
1420
+ };
1421
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderPrimitiveContext.Provider, { value: { components: resolvedComponents, readOnly }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1422
+ Section,
1030
1423
  {
1031
1424
  className: `form-engine-builder ${className}`.trim(),
1032
1425
  "aria-label": translate("builder.formBuilder"),
@@ -1045,362 +1438,459 @@ function FormBuilder({
1045
1438
  addOption(fieldId);
1046
1439
  }
1047
1440
  },
1048
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { className: "form-engine-builder__controls", disabled: readOnly, children: [
1049
- pagesEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "form-engine-builder__pages", "aria-labelledby": "builder-pages-heading", children: [
1050
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: "builder-pages-heading", children: translate("builder.pages") }),
1051
- schema.pages === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: enablePages, children: translate("builder.enablePages") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1052
- schema.pages.map((page, pageIndex) => {
1053
- const priorQuestionIds = new Set(
1054
- schema.pages?.slice(0, pageIndex).flatMap((item) => item.questionIds)
1055
- );
1056
- const availableSources = schema.fields.filter((field) => priorQuestionIds.has(field.id));
1057
- const source = schema.fields.find((field) => field.id === page.displayCondition?.questionId);
1058
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { className: "form-engine-builder__page", children: [
1059
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("legend", { children: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}` }),
1060
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__toolbar", children: [
1441
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Fieldset, { className: "form-engine-builder__controls", disabled: readOnly, children: [
1442
+ pagesEnabled ? PagesSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1443
+ Section,
1444
+ {
1445
+ className: "form-engine-builder__pages",
1446
+ headingId: "builder-pages-heading",
1447
+ title: translate("builder.pages"),
1448
+ children: schema.pages === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { onClick: enablePages, children: translate("builder.enablePages") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1449
+ schema.pages.map((page, pageIndex) => {
1450
+ const priorQuestionIds = new Set(
1451
+ schema.pages?.slice(0, pageIndex).flatMap((item) => item.questionIds)
1452
+ );
1453
+ const availableSources = schema.fields.filter((field) => priorQuestionIds.has(field.id));
1454
+ const source = schema.fields.find((field) => field.id === page.displayCondition?.questionId);
1455
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1456
+ Fieldset,
1457
+ {
1458
+ className: "form-engine-builder__page",
1459
+ legend: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}`,
1460
+ children: [
1461
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "form-engine-builder__toolbar", children: ToolbarSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1462
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1463
+ IconButton,
1464
+ {
1465
+ icon: "\u2191",
1466
+ title: translate("builder.moveUp", { title: page.title ?? page.id }),
1467
+ disabled: pageIndex === 0,
1468
+ onClick: () => movePage(pageIndex, -1)
1469
+ }
1470
+ ),
1471
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1472
+ IconButton,
1473
+ {
1474
+ icon: "\u2193",
1475
+ title: translate("builder.moveDown", { title: page.title ?? page.id }),
1476
+ disabled: pageIndex === (schema.pages?.length ?? 0) - 1,
1477
+ onClick: () => movePage(pageIndex, 1)
1478
+ }
1479
+ ),
1480
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { onClick: () => removePage(pageIndex), variant: "danger", children: translate("builder.deleteAction") })
1481
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1482
+ ToolbarSlot,
1483
+ {
1484
+ schema,
1485
+ kind: "page",
1486
+ targetId: page.id,
1487
+ index: pageIndex,
1488
+ total: schema.pages?.length ?? 0,
1489
+ title: page.title ?? page.id,
1490
+ onMoveUp: () => movePage(pageIndex, -1),
1491
+ onMoveDown: () => movePage(pageIndex, 1),
1492
+ onRemove: () => removePage(pageIndex),
1493
+ readOnly,
1494
+ actions,
1495
+ components
1496
+ }
1497
+ ) }),
1498
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1499
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1500
+ translate("builder.pageTitle"),
1501
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1502
+ TextInput,
1503
+ {
1504
+ value: page.title ?? "",
1505
+ onChange: (value) => {
1506
+ updatePage(page.id, (current) => {
1507
+ if (value.length > 0) return { ...current, title: value };
1508
+ const { title: _title, ...withoutTitle } = current;
1509
+ return withoutTitle;
1510
+ });
1511
+ }
1512
+ }
1513
+ )
1514
+ ] }),
1515
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1516
+ translate("builder.pageDescription"),
1517
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1518
+ TextInput,
1519
+ {
1520
+ value: page.description ?? "",
1521
+ onChange: (value) => {
1522
+ updatePage(page.id, (current) => {
1523
+ if (value.length > 0) return { ...current, description: value };
1524
+ const { description: _description, ...withoutDescription } = current;
1525
+ return withoutDescription;
1526
+ });
1527
+ }
1528
+ }
1529
+ )
1530
+ ] })
1531
+ ] }),
1532
+ !localizationEnabled || editingLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__translation-editor", children: [
1533
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: editingLocale }),
1534
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1535
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1536
+ translate("builder.pageTitle"),
1537
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1538
+ TextInput,
1539
+ {
1540
+ value: page.translations?.[editingLocale]?.title ?? "",
1541
+ onChange: (value) => updateManualTranslation({
1542
+ locale: editingLocale,
1543
+ kind: "page",
1544
+ nodeId: page.id,
1545
+ property: "title",
1546
+ sourceText: page.title ?? "",
1547
+ translatedText: value,
1548
+ ...page.translationMetadata?.[editingLocale]?.title === void 0 ? {} : {
1549
+ existingTranslationMetadata: page.translationMetadata[editingLocale]?.title
1550
+ }
1551
+ })
1552
+ }
1553
+ )
1554
+ ] }),
1555
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1556
+ translate("builder.pageDescription"),
1557
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1558
+ TextInput,
1559
+ {
1560
+ value: page.translations?.[editingLocale]?.description ?? "",
1561
+ onChange: (value) => updateManualTranslation({
1562
+ locale: editingLocale,
1563
+ kind: "page",
1564
+ nodeId: page.id,
1565
+ property: "description",
1566
+ sourceText: page.description ?? "",
1567
+ translatedText: value,
1568
+ ...page.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
1569
+ existingTranslationMetadata: page.translationMetadata[editingLocale]?.description
1570
+ }
1571
+ })
1572
+ }
1573
+ )
1574
+ ] })
1575
+ ] })
1576
+ ] }),
1577
+ conditionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__condition", children: [
1578
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1579
+ translate("builder.pageCondition"),
1580
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1581
+ Select,
1582
+ {
1583
+ value: page.displayCondition?.questionId ?? "",
1584
+ onChange: (value) => {
1585
+ const selected = schema.fields.find((field) => field.id === value);
1586
+ updatePage(page.id, (current) => {
1587
+ if (selected === void 0) {
1588
+ const { displayCondition: _condition, ...withoutCondition } = current;
1589
+ return withoutCondition;
1590
+ }
1591
+ return {
1592
+ ...current,
1593
+ displayCondition: conditionWithValue(
1594
+ selected.id,
1595
+ conditionOperators(selected)[0] ?? "not_empty",
1596
+ defaultConditionValue(selected)
1597
+ )
1598
+ };
1599
+ });
1600
+ },
1601
+ options: [
1602
+ { value: "", label: translate("builder.alwaysVisible") },
1603
+ ...availableSources.map((field) => ({ value: field.id, label: field.title }))
1604
+ ]
1605
+ }
1606
+ )
1607
+ ] }),
1608
+ page.displayCondition !== void 0 && source !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1609
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1610
+ Select,
1611
+ {
1612
+ "aria-label": translate("builder.conditionOperator"),
1613
+ value: page.displayCondition.operator,
1614
+ onChange: (value) => {
1615
+ const operator = value;
1616
+ updatePage(page.id, (current) => ({
1617
+ ...current,
1618
+ displayCondition: conditionWithValue(
1619
+ source.id,
1620
+ operator,
1621
+ defaultConditionValue(source)
1622
+ )
1623
+ }));
1624
+ },
1625
+ options: conditionOperators(source).map((operator) => ({
1626
+ value: operator,
1627
+ label: translate(operatorKey(operator))
1628
+ }))
1629
+ }
1630
+ ),
1631
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1632
+ ConditionValueEditor,
1633
+ {
1634
+ source,
1635
+ condition: page.displayCondition,
1636
+ onChange: (condition) => updatePage(page.id, (current) => ({ ...current, displayCondition: condition })),
1637
+ translate,
1638
+ components
1639
+ }
1640
+ )
1641
+ ] }) : null
1642
+ ] }) : null
1643
+ ]
1644
+ },
1645
+ page.id
1646
+ );
1647
+ }),
1648
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__page-add", children: [
1649
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1650
+ translate("builder.pageQuestion"),
1061
1651
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1062
- "button",
1652
+ Select,
1063
1653
  {
1064
- type: "button",
1065
- disabled: pageIndex === 0,
1066
- "aria-label": translate("builder.moveUp", { title: page.title ?? page.id }),
1067
- onClick: () => movePage(pageIndex, -1),
1068
- children: "\u2191"
1654
+ value: newPageQuestionId,
1655
+ disabled: movablePageQuestions.length === 0,
1656
+ onChange: setNewPageQuestionId,
1657
+ options: [
1658
+ { value: "", label: "\u2014" },
1659
+ ...schema.fields.filter((field) => movablePageQuestions.includes(field.id)).map((field) => ({ value: field.id, label: field.title }))
1660
+ ]
1069
1661
  }
1070
- ),
1071
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1072
- "button",
1662
+ )
1663
+ ] }),
1664
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { disabled: movablePageQuestions.length === 0, onClick: addPage, children: translate("builder.addPage") })
1665
+ ] })
1666
+ ] })
1667
+ }
1668
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1669
+ PagesSlot,
1670
+ {
1671
+ schema,
1672
+ currentLocale: editingLocale,
1673
+ readOnly,
1674
+ actions,
1675
+ components
1676
+ }
1677
+ ) : null,
1678
+ localizationEnabled ? LocalizationSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1679
+ Section,
1680
+ {
1681
+ className: "form-engine-builder__localization",
1682
+ headingId: "builder-localization-heading",
1683
+ title: translate("builder.localization"),
1684
+ children: [
1685
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1686
+ translate("builder.completionMessage"),
1687
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1688
+ TextInput,
1689
+ {
1690
+ value: schema.completionMessage ?? "",
1691
+ onChange: (value) => setSourceText({ kind: "form" }, "completionMessage", value)
1692
+ }
1693
+ )
1694
+ ] }),
1695
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1696
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1697
+ translate("builder.defaultLocale"),
1698
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextInput, { value: schema.defaultLocale ?? "", onChange: setDefaultLocale })
1699
+ ] }),
1700
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { htmlFor: "builder-new-locale", children: [
1701
+ translate("builder.addLocale"),
1702
+ availableAllowedLocales === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextInput, { id: "builder-new-locale", value: newLocale, onChange: setNewLocale }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1703
+ Select,
1073
1704
  {
1074
- type: "button",
1075
- disabled: pageIndex === (schema.pages?.length ?? 0) - 1,
1076
- "aria-label": translate("builder.moveDown", { title: page.title ?? page.id }),
1077
- onClick: () => movePage(pageIndex, 1),
1078
- children: "\u2193"
1705
+ id: "builder-new-locale",
1706
+ value: newLocale,
1707
+ onChange: setNewLocale,
1708
+ options: [
1709
+ { value: "", label: "\u2014" },
1710
+ ...availableAllowedLocales.map((candidate) => ({ value: candidate, label: candidate }))
1711
+ ]
1079
1712
  }
1080
- ),
1081
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => removePage(pageIndex), children: translate("builder.deleteAction") })
1082
- ] }),
1083
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1084
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1085
- translate("builder.pageTitle"),
1086
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1087
- "input",
1088
- {
1089
- value: page.title ?? "",
1090
- onChange: (event) => {
1091
- const value = event.currentTarget.value;
1092
- updatePage(page.id, (current) => {
1093
- if (value.length > 0) return { ...current, title: value };
1094
- const { title: _title, ...withoutTitle } = current;
1095
- return withoutTitle;
1096
- });
1097
- }
1098
- }
1099
- )
1100
- ] }),
1101
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1102
- translate("builder.pageDescription"),
1103
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1104
- "input",
1105
- {
1106
- value: page.description ?? "",
1107
- onChange: (event) => {
1108
- const value = event.currentTarget.value;
1109
- updatePage(page.id, (current) => {
1110
- if (value.length > 0) return { ...current, description: value };
1111
- const { description: _description, ...withoutDescription } = current;
1112
- return withoutDescription;
1113
- });
1114
- }
1115
- }
1116
- )
1117
- ] })
1713
+ )
1118
1714
  ] }),
1119
- !localizationEnabled || editingLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__translation-editor", children: [
1120
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: editingLocale }),
1121
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1122
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1123
- translate("builder.pageTitle"),
1124
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1125
- "input",
1126
- {
1127
- value: page.translations?.[editingLocale]?.title ?? "",
1128
- onChange: (event) => updateManualTranslation({
1129
- locale: editingLocale,
1130
- kind: "page",
1131
- nodeId: page.id,
1132
- property: "title",
1133
- sourceText: page.title ?? "",
1134
- translatedText: event.currentTarget.value,
1135
- ...page.translationMetadata?.[editingLocale]?.title === void 0 ? {} : {
1136
- existingTranslationMetadata: page.translationMetadata[editingLocale]?.title
1137
- }
1138
- })
1139
- }
1140
- )
1141
- ] }),
1142
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1143
- translate("builder.pageDescription"),
1144
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1145
- "input",
1146
- {
1147
- value: page.translations?.[editingLocale]?.description ?? "",
1148
- onChange: (event) => updateManualTranslation({
1149
- locale: editingLocale,
1150
- kind: "page",
1151
- nodeId: page.id,
1152
- property: "description",
1153
- sourceText: page.description ?? "",
1154
- translatedText: event.currentTarget.value,
1155
- ...page.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
1156
- existingTranslationMetadata: page.translationMetadata[editingLocale]?.description
1157
- }
1158
- })
1159
- }
1160
- )
1161
- ] })
1162
- ] })
1715
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1716
+ Button,
1717
+ {
1718
+ action: "addLocale",
1719
+ disabled: newLocale.trim().length === 0 || localeLimitReached,
1720
+ onClick: addLocale,
1721
+ children: translate("builder.addLocale")
1722
+ }
1723
+ ),
1724
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1725
+ translate("builder.editLocale"),
1726
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1727
+ Select,
1728
+ {
1729
+ value: editingLocale,
1730
+ onChange: setEditingLocale,
1731
+ options: [
1732
+ { value: "", label: "\u2014" },
1733
+ ...(schema.supportedLocales ?? []).filter((item) => item !== schema.defaultLocale).map((item) => ({ value: item, label: item }))
1734
+ ]
1735
+ }
1736
+ )
1163
1737
  ] }),
1164
- conditionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__condition", children: [
1165
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1166
- translate("builder.pageCondition"),
1167
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1168
- "select",
1169
- {
1170
- value: page.displayCondition?.questionId ?? "",
1171
- onChange: (event) => {
1172
- const selected = schema.fields.find((field) => field.id === event.currentTarget.value);
1173
- updatePage(page.id, (current) => {
1174
- if (selected === void 0) {
1175
- const { displayCondition: _condition, ...withoutCondition } = current;
1176
- return withoutCondition;
1177
- }
1178
- return {
1179
- ...current,
1180
- displayCondition: conditionWithValue(
1181
- selected.id,
1182
- conditionOperators(selected)[0] ?? "not_empty",
1183
- defaultConditionValue(selected)
1184
- )
1185
- };
1186
- });
1187
- },
1188
- children: [
1189
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: translate("builder.alwaysVisible") }),
1190
- availableSources.map((field) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: field.id, children: field.title }, field.id))
1191
- ]
1192
- }
1193
- )
1194
- ] }),
1195
- page.displayCondition !== void 0 && source !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1196
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1197
- "select",
1198
- {
1199
- "aria-label": translate("builder.conditionOperator"),
1200
- value: page.displayCondition.operator,
1201
- onChange: (event) => {
1202
- const operator = event.currentTarget.value;
1203
- updatePage(page.id, (current) => ({
1204
- ...current,
1205
- displayCondition: conditionWithValue(
1206
- source.id,
1207
- operator,
1208
- defaultConditionValue(source)
1209
- )
1210
- }));
1211
- },
1212
- children: conditionOperators(source).map((operator) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: operator, children: translate(operatorKey(operator)) }, operator))
1213
- }
1214
- ),
1215
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1216
- ConditionValueEditor,
1217
- {
1218
- source,
1219
- condition: page.displayCondition,
1220
- onChange: (condition) => updatePage(page.id, (current) => ({ ...current, displayCondition: condition })),
1221
- translate
1222
- }
1223
- )
1224
- ] }) : null
1225
- ] }) : null
1226
- ] }, page.id);
1227
- }),
1228
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__page-add", children: [
1229
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1230
- translate("builder.pageQuestion"),
1231
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1232
- "select",
1738
+ TranslationActionsSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1739
+ Button,
1233
1740
  {
1234
- value: newPageQuestionId,
1235
- disabled: movablePageQuestions.length === 0,
1236
- onChange: (event) => setNewPageQuestionId(event.currentTarget.value),
1237
- children: [
1238
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u2014" }),
1239
- schema.fields.filter((field) => movablePageQuestions.includes(field.id)).map((field) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: field.id, children: field.title }, field.id))
1240
- ]
1741
+ disabled: translationAdapter === void 0 || editingLocale.length === 0 || isTranslating,
1742
+ onClick: () => void translateAll(),
1743
+ children: translate("builder.autoTranslate")
1744
+ }
1745
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1746
+ TranslationActionsSlot,
1747
+ {
1748
+ schema,
1749
+ currentLocale: editingLocale,
1750
+ onAutoTranslate: () => void translateAll(),
1751
+ isTranslating,
1752
+ ...translationError === null ? {} : { translationError },
1753
+ ...translationReport === void 0 ? {} : { translationReport },
1754
+ onClearTranslationError: () => setTranslationError(null),
1755
+ readOnly,
1756
+ actions,
1757
+ components
1241
1758
  }
1242
1759
  )
1243
1760
  ] }),
1244
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: movablePageQuestions.length === 0, onClick: addPage, children: translate("builder.addPage") })
1245
- ] })
1246
- ] })
1247
- ] }) : null,
1248
- localizationEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "form-engine-builder__localization", "aria-labelledby": "builder-localization-heading", children: [
1249
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: "builder-localization-heading", children: translate("builder.localization") }),
1250
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1251
- translate("builder.completionMessage"),
1252
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1253
- "input",
1254
- {
1255
- value: schema.completionMessage ?? "",
1256
- onChange: (event) => setSourceText({ kind: "form" }, "completionMessage", event.currentTarget.value)
1257
- }
1258
- )
1259
- ] }),
1260
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1261
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1262
- translate("builder.defaultLocale"),
1263
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1264
- "input",
1265
- {
1266
- value: schema.defaultLocale ?? "",
1267
- onChange: (event) => setDefaultLocale(event.currentTarget.value)
1268
- }
1269
- )
1270
- ] }),
1271
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { htmlFor: "builder-new-locale", children: [
1272
- translate("builder.addLocale"),
1273
- availableAllowedLocales === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1274
- "input",
1275
- {
1276
- id: "builder-new-locale",
1277
- value: newLocale,
1278
- onChange: (event) => setNewLocale(event.currentTarget.value)
1279
- }
1280
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1281
- "select",
1282
- {
1283
- id: "builder-new-locale",
1284
- value: newLocale,
1285
- onChange: (event) => setNewLocale(event.currentTarget.value),
1286
- children: [
1287
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u2014" }),
1288
- availableAllowedLocales.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: candidate, children: candidate }, candidate))
1289
- ]
1290
- }
1291
- )
1292
- ] }),
1293
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1294
- "button",
1295
- {
1296
- type: "button",
1297
- "data-builder-action": "addLocale",
1298
- disabled: newLocale.trim().length === 0 || localeLimitReached,
1299
- onClick: addLocale,
1300
- children: translate("builder.addLocale")
1301
- }
1302
- ),
1303
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1304
- translate("builder.editLocale"),
1305
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: editingLocale, onChange: (event) => setEditingLocale(event.currentTarget.value), children: [
1306
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u2014" }),
1307
- (schema.supportedLocales ?? []).filter((item) => item !== schema.defaultLocale).map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: item, children: item }, item))
1761
+ translationAdapter === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: translate("builder.translationUnavailable") }) : null,
1762
+ translationError === null ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorMessage, { message: translationError }),
1763
+ editingLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1764
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1765
+ translate("builder.questionTitle"),
1766
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1767
+ TextInput,
1768
+ {
1769
+ value: schema.translations?.[editingLocale]?.title ?? "",
1770
+ onChange: (value) => updateFormTranslation("title", value)
1771
+ }
1772
+ )
1773
+ ] }),
1774
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1775
+ translate("builder.pageDescription"),
1776
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1777
+ TextInput,
1778
+ {
1779
+ value: schema.translations?.[editingLocale]?.description ?? "",
1780
+ onChange: (value) => updateFormTranslation("description", value)
1781
+ }
1782
+ )
1783
+ ] }),
1784
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1785
+ translate("builder.completionMessage"),
1786
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1787
+ TextInput,
1788
+ {
1789
+ value: schema.translations?.[editingLocale]?.completionMessage ?? "",
1790
+ onChange: (value) => updateFormTranslation("completionMessage", value)
1791
+ }
1792
+ )
1793
+ ] })
1308
1794
  ] })
1309
- ] }),
1310
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1311
- "button",
1312
- {
1313
- type: "button",
1314
- disabled: translationAdapter === void 0 || editingLocale.length === 0 || isTranslating,
1315
- onClick: () => void translateAll(),
1316
- children: translate("builder.autoTranslate")
1317
- }
1318
- )
1319
- ] }),
1320
- translationAdapter === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: translate("builder.translationUnavailable") }) : null,
1321
- translationError === null ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "form-engine-builder__error", children: translationError }),
1322
- editingLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1323
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1324
- translate("builder.questionTitle"),
1325
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1326
- "input",
1327
- {
1328
- value: schema.translations?.[editingLocale]?.title ?? "",
1329
- onChange: (event) => updateFormTranslation("title", event.currentTarget.value)
1330
- }
1331
- )
1332
- ] }),
1333
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1334
- translate("builder.pageDescription"),
1335
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1336
- "input",
1337
- {
1338
- value: schema.translations?.[editingLocale]?.description ?? "",
1339
- onChange: (event) => updateFormTranslation("description", event.currentTarget.value)
1340
- }
1341
- )
1342
- ] }),
1343
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1344
- translate("builder.completionMessage"),
1345
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1346
- "input",
1347
- {
1348
- value: schema.translations?.[editingLocale]?.completionMessage ?? "",
1349
- onChange: (event) => updateFormTranslation("completionMessage", event.currentTarget.value)
1350
- }
1351
- )
1352
- ] })
1353
- ] })
1354
- ] }) : null,
1795
+ ]
1796
+ }
1797
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1798
+ LocalizationSlot,
1799
+ {
1800
+ schema,
1801
+ currentLocale: editingLocale,
1802
+ onCurrentLocaleChange: setEditingLocale,
1803
+ onAutoTranslate: () => void translateAll(),
1804
+ isTranslating,
1805
+ ...translationError === null ? {} : { translationError },
1806
+ readOnly,
1807
+ actions,
1808
+ components
1809
+ }
1810
+ ) : null,
1355
1811
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "form-engine-builder__list", children: schema.fields.map((field, index) => {
1356
1812
  const condition = field.displayCondition;
1357
1813
  const source = condition === void 0 ? void 0 : schema.fields.find((item) => item.id === condition.questionId);
1358
1814
  const availableSources = schema.fields.slice(0, index);
1359
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { className: "form-engine-builder__question", children: [
1360
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("legend", { children: field.title }),
1361
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__toolbar", children: [
1815
+ if (FieldEditorSlot !== void 0) {
1816
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1817
+ FieldEditorSlot,
1818
+ {
1819
+ schema,
1820
+ field,
1821
+ index,
1822
+ currentLocale: editingLocale,
1823
+ ...policy === void 0 ? {} : { policy },
1824
+ readOnly,
1825
+ actions,
1826
+ components
1827
+ },
1828
+ field.id
1829
+ );
1830
+ }
1831
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Fieldset, { className: "form-engine-builder__question", legend: field.title, children: [
1832
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "form-engine-builder__toolbar", children: ToolbarSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1362
1833
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1363
- "button",
1834
+ IconButton,
1364
1835
  {
1365
- type: "button",
1836
+ icon: "\u2191",
1837
+ title: translate("builder.moveUp", { title: field.title }),
1366
1838
  disabled: index === 0,
1367
- onClick: () => moveField(index, -1),
1368
- "aria-label": translate("builder.moveUp", { title: field.title }),
1369
- children: "\u2191"
1839
+ onClick: () => moveField(index, -1)
1370
1840
  }
1371
1841
  ),
1372
1842
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1373
- "button",
1843
+ IconButton,
1374
1844
  {
1375
- type: "button",
1845
+ icon: "\u2193",
1846
+ title: translate("builder.moveDown", { title: field.title }),
1376
1847
  disabled: index === schema.fields.length - 1,
1377
- onClick: () => moveField(index, 1),
1378
- "aria-label": translate("builder.moveDown", { title: field.title }),
1379
- children: "\u2193"
1848
+ onClick: () => moveField(index, 1)
1380
1849
  }
1381
1850
  ),
1382
1851
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1383
- "button",
1852
+ Button,
1384
1853
  {
1385
- type: "button",
1386
1854
  disabled: schema.fields.length === 1,
1387
1855
  onClick: () => removeField(field.id),
1388
1856
  "aria-label": translate("builder.delete", { title: field.title }),
1857
+ variant: "danger",
1389
1858
  children: translate("builder.deleteAction")
1390
1859
  }
1391
1860
  )
1392
- ] }),
1861
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1862
+ ToolbarSlot,
1863
+ {
1864
+ schema,
1865
+ kind: "field",
1866
+ targetId: field.id,
1867
+ index,
1868
+ total: schema.fields.length,
1869
+ title: field.title,
1870
+ onMoveUp: () => moveField(index, -1),
1871
+ onMoveDown: () => moveField(index, 1),
1872
+ onRemove: () => removeField(field.id),
1873
+ readOnly,
1874
+ actions,
1875
+ components
1876
+ }
1877
+ ) }),
1393
1878
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1394
1879
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1395
1880
  translate("builder.questionTitle"),
1396
1881
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1397
- "input",
1882
+ TextInput,
1398
1883
  {
1884
+ name: `fields.${field.id}.title`,
1885
+ label: translate("builder.questionTitle"),
1886
+ required: true,
1887
+ error: field.title.trim().length === 0,
1888
+ helperText: field.title.trim().length === 0 ? translate("builder.required") : "",
1399
1889
  value: field.title,
1400
1890
  placeholder: translate("builder.questionTitlePlaceholder"),
1401
- onChange: (event) => updateField(field.id, (current) => ({
1891
+ onChange: (value) => updateField(field.id, (current) => ({
1402
1892
  ...current,
1403
- title: event.currentTarget.value.trim().length === 0 ? current.title : event.currentTarget.value
1893
+ title: value.trim().length === 0 ? current.title : value
1404
1894
  }))
1405
1895
  }
1406
1896
  )
@@ -1408,36 +1898,37 @@ function FormBuilder({
1408
1898
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1409
1899
  translate("builder.type"),
1410
1900
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1411
- "select",
1901
+ Select,
1412
1902
  {
1413
1903
  value: field.type,
1414
- onChange: (event) => changeType(field.id, event.currentTarget.value),
1415
- children: FIELD_TYPES.filter(
1904
+ onChange: (value) => changeType(field.id, value),
1905
+ options: FIELD_TYPES.filter(
1416
1906
  (type) => policy?.allowedFieldTypes === void 0 || policy.allowedFieldTypes.includes(type)
1417
- ).map((type) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: type, children: translate(fieldTypeKey(type)) }, type))
1907
+ ).map((type) => ({ value: type, label: translate(fieldTypeKey(type)) }))
1418
1908
  }
1419
1909
  )
1420
1910
  ] }),
1421
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "form-engine-builder__check", children: [
1422
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1423
- "input",
1424
- {
1425
- type: "checkbox",
1426
- checked: field.required === true,
1427
- onChange: (event) => updateField(field.id, (current) => ({ ...current, required: event.currentTarget.checked }))
1428
- }
1429
- ),
1430
- translate("builder.required")
1431
- ] })
1911
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1912
+ Checkbox,
1913
+ {
1914
+ className: "form-engine-builder__check",
1915
+ checked: field.required === true,
1916
+ onChange: (checked) => updateField(field.id, (current) => ({ ...current, required: checked })),
1917
+ label: translate("builder.required")
1918
+ }
1919
+ )
1432
1920
  ] }),
1433
1921
  !pagesEnabled || schema.pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1434
1922
  translate("builder.questionPage"),
1435
1923
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1436
- "select",
1924
+ Select,
1437
1925
  {
1438
1926
  value: pageForField(field.id)?.id ?? "",
1439
- onChange: (event) => assignFieldToPage(field.id, event.currentTarget.value),
1440
- children: schema.pages.map((page, pageIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: page.id, children: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}` }, page.id))
1927
+ onChange: (value) => assignFieldToPage(field.id, value),
1928
+ options: schema.pages.map((page, pageIndex) => ({
1929
+ value: page.id,
1930
+ label: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}`
1931
+ }))
1441
1932
  }
1442
1933
  )
1443
1934
  ] }),
@@ -1447,16 +1938,16 @@ function FormBuilder({
1447
1938
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1448
1939
  translate("builder.questionTitle"),
1449
1940
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1450
- "input",
1941
+ TextInput,
1451
1942
  {
1452
1943
  value: field.translations?.[editingLocale]?.title ?? "",
1453
- onChange: (event) => updateManualTranslation({
1944
+ onChange: (value) => updateManualTranslation({
1454
1945
  locale: editingLocale,
1455
1946
  kind: "field",
1456
1947
  nodeId: field.id,
1457
1948
  property: "title",
1458
1949
  sourceText: field.title,
1459
- translatedText: event.currentTarget.value,
1950
+ translatedText: value,
1460
1951
  ...field.translationMetadata?.[editingLocale]?.title === void 0 ? {} : {
1461
1952
  existingTranslationMetadata: field.translationMetadata[editingLocale]?.title
1462
1953
  }
@@ -1467,16 +1958,16 @@ function FormBuilder({
1467
1958
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1468
1959
  translate("builder.pageDescription"),
1469
1960
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1470
- "input",
1961
+ TextInput,
1471
1962
  {
1472
1963
  value: field.translations?.[editingLocale]?.description ?? "",
1473
- onChange: (event) => updateManualTranslation({
1964
+ onChange: (value) => updateManualTranslation({
1474
1965
  locale: editingLocale,
1475
1966
  kind: "field",
1476
1967
  nodeId: field.id,
1477
1968
  property: "description",
1478
1969
  sourceText: field.description ?? "",
1479
- translatedText: event.currentTarget.value,
1970
+ translatedText: value,
1480
1971
  ...field.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
1481
1972
  existingTranslationMetadata: field.translationMetadata[editingLocale]?.description
1482
1973
  }
@@ -1491,16 +1982,16 @@ function FormBuilder({
1491
1982
  editingLocale,
1492
1983
  ")",
1493
1984
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1494
- "input",
1985
+ TextInput,
1495
1986
  {
1496
1987
  value: option.translations?.[editingLocale] ?? "",
1497
- onChange: (event) => updateManualTranslation({
1988
+ onChange: (value) => updateManualTranslation({
1498
1989
  locale: editingLocale,
1499
1990
  kind: "option",
1500
1991
  nodeId: option.id,
1501
1992
  property: "label",
1502
1993
  sourceText: option.label,
1503
- translatedText: event.currentTarget.value,
1994
+ translatedText: value,
1504
1995
  ...option.translationMetadata?.[editingLocale]?.label === void 0 ? {} : {
1505
1996
  existingTranslationMetadata: option.translationMetadata[editingLocale]?.label
1506
1997
  }
@@ -1513,12 +2004,12 @@ function FormBuilder({
1513
2004
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1514
2005
  translate("builder.minimum"),
1515
2006
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1516
- "input",
2007
+ TextInput,
1517
2008
  {
1518
2009
  type: "number",
1519
- value: field.min ?? 1,
1520
- onChange: (event) => {
1521
- const min = event.currentTarget.valueAsNumber;
2010
+ value: String(field.min ?? 1),
2011
+ onChange: (value) => {
2012
+ const min = Number(value);
1522
2013
  if (!Number.isInteger(min)) return;
1523
2014
  updateField(
1524
2015
  field.id,
@@ -1531,12 +2022,12 @@ function FormBuilder({
1531
2022
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1532
2023
  translate("builder.maximum"),
1533
2024
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1534
- "input",
2025
+ TextInput,
1535
2026
  {
1536
2027
  type: "number",
1537
- value: field.max ?? 5,
1538
- onChange: (event) => {
1539
- const max = event.currentTarget.valueAsNumber;
2028
+ value: String(field.max ?? 5),
2029
+ onChange: (value) => {
2030
+ const max = Number(value);
1540
2031
  if (!Number.isInteger(max)) return;
1541
2032
  updateField(
1542
2033
  field.id,
@@ -1549,52 +2040,82 @@ function FormBuilder({
1549
2040
  ] }) : null,
1550
2041
  "options" in field ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__options", children: [
1551
2042
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: translate("builder.options") }),
1552
- field.options.map((option, optionIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__option", children: [
1553
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1554
- "input",
1555
- {
1556
- "aria-label": translate("builder.optionLabel", { index: optionIndex + 1 }),
1557
- value: option.label,
1558
- placeholder: translate("builder.optionLabelPlaceholder"),
1559
- onChange: (event) => event.currentTarget.value.trim().length === 0 ? void 0 : updateOption(field.id, option.id, event.currentTarget.value)
1560
- }
1561
- ),
1562
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1563
- "button",
1564
- {
1565
- type: "button",
1566
- disabled: optionIndex === 0,
1567
- "aria-label": translate("builder.moveUp", { title: option.label }),
1568
- onClick: () => moveOption(field.id, option.id, optionIndex - 1),
1569
- children: "\u2191"
1570
- }
1571
- ),
1572
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1573
- "button",
1574
- {
1575
- type: "button",
1576
- disabled: optionIndex === field.options.length - 1,
1577
- "aria-label": translate("builder.moveDown", { title: option.label }),
1578
- onClick: () => moveOption(field.id, option.id, optionIndex + 1),
1579
- children: "\u2193"
1580
- }
1581
- ),
1582
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1583
- "button",
2043
+ field.options.map(
2044
+ (option, optionIndex) => OptionEditorSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__option", children: [
2045
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2046
+ TextInput,
2047
+ {
2048
+ "aria-label": translate("builder.optionLabel", { index: optionIndex + 1 }),
2049
+ value: option.label,
2050
+ placeholder: translate("builder.optionLabelPlaceholder"),
2051
+ onChange: (value) => value.trim().length === 0 ? void 0 : updateOption(field.id, option.id, value)
2052
+ }
2053
+ ),
2054
+ ToolbarSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2055
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2056
+ IconButton,
2057
+ {
2058
+ icon: "\u2191",
2059
+ title: translate("builder.moveUp", { title: option.label }),
2060
+ disabled: optionIndex === 0,
2061
+ onClick: () => moveOption(field.id, option.id, optionIndex - 1)
2062
+ }
2063
+ ),
2064
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2065
+ IconButton,
2066
+ {
2067
+ icon: "\u2193",
2068
+ title: translate("builder.moveDown", { title: option.label }),
2069
+ disabled: optionIndex === field.options.length - 1,
2070
+ onClick: () => moveOption(field.id, option.id, optionIndex + 1)
2071
+ }
2072
+ ),
2073
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2074
+ Button,
2075
+ {
2076
+ disabled: field.options.length === 1,
2077
+ onClick: () => removeOption(field.id, option.id),
2078
+ variant: "danger",
2079
+ children: translate("builder.remove")
2080
+ }
2081
+ )
2082
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2083
+ ToolbarSlot,
2084
+ {
2085
+ schema,
2086
+ kind: "option",
2087
+ targetId: option.id,
2088
+ index: optionIndex,
2089
+ total: field.options.length,
2090
+ title: option.label,
2091
+ onMoveUp: () => moveOption(field.id, option.id, optionIndex - 1),
2092
+ onMoveDown: () => moveOption(field.id, option.id, optionIndex + 1),
2093
+ onRemove: () => removeOption(field.id, option.id),
2094
+ readOnly,
2095
+ actions,
2096
+ components
2097
+ }
2098
+ )
2099
+ ] }, option.id) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2100
+ OptionEditorSlot,
1584
2101
  {
1585
- type: "button",
1586
- disabled: field.options.length === 1,
1587
- onClick: () => removeOption(field.id, option.id),
1588
- children: translate("builder.remove")
1589
- }
2102
+ schema,
2103
+ field,
2104
+ option,
2105
+ index: optionIndex,
2106
+ currentLocale: editingLocale,
2107
+ readOnly,
2108
+ actions,
2109
+ components
2110
+ },
2111
+ option.id
1590
2112
  )
1591
- ] }, option.id)),
2113
+ ),
1592
2114
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1593
- "button",
2115
+ Button,
1594
2116
  {
1595
- type: "button",
1596
- "data-builder-action": "addOption",
1597
- "data-target-id": field.id,
2117
+ action: "addOption",
2118
+ targetId: field.id,
1598
2119
  disabled: policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
1599
2120
  onClick: () => addOption(field.id),
1600
2121
  children: translate("builder.addOption")
@@ -1604,12 +2125,12 @@ function FormBuilder({
1604
2125
  conditionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__condition", children: [
1605
2126
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1606
2127
  translate("builder.displayCondition"),
1607
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1608
- "select",
2128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2129
+ Select,
1609
2130
  {
1610
2131
  value: condition?.questionId ?? "",
1611
- onChange: (event) => {
1612
- const selected = schema.fields.find((item) => item.id === event.currentTarget.value);
2132
+ onChange: (value) => {
2133
+ const selected = schema.fields.find((item) => item.id === value);
1613
2134
  setDisplayCondition(
1614
2135
  field.id,
1615
2136
  selected === void 0 ? void 0 : conditionWithValue(
@@ -1619,27 +2140,30 @@ function FormBuilder({
1619
2140
  )
1620
2141
  );
1621
2142
  },
1622
- children: [
1623
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: translate("builder.alwaysVisible") }),
1624
- availableSources.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: candidate.id, children: candidate.title }, candidate.id))
2143
+ options: [
2144
+ { value: "", label: translate("builder.alwaysVisible") },
2145
+ ...availableSources.map((candidate) => ({ value: candidate.id, label: candidate.title }))
1625
2146
  ]
1626
2147
  }
1627
2148
  )
1628
2149
  ] }),
1629
2150
  condition !== void 0 && source !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1630
2151
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1631
- "select",
2152
+ Select,
1632
2153
  {
1633
2154
  "aria-label": translate("builder.conditionOperator"),
1634
2155
  value: condition.operator,
1635
- onChange: (event) => {
1636
- const operator = event.currentTarget.value;
2156
+ onChange: (value) => {
2157
+ const operator = value;
1637
2158
  setDisplayCondition(
1638
2159
  field.id,
1639
2160
  conditionWithValue(source.id, operator, defaultConditionValue(source))
1640
2161
  );
1641
2162
  },
1642
- children: conditionOperators(source).map((operator) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: operator, children: translate(operatorKey(operator)) }, operator))
2163
+ options: conditionOperators(source).map((operator) => ({
2164
+ value: operator,
2165
+ label: translate(operatorKey(operator))
2166
+ }))
1643
2167
  }
1644
2168
  ),
1645
2169
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1648,7 +2172,8 @@ function FormBuilder({
1648
2172
  source,
1649
2173
  condition,
1650
2174
  onChange: (next) => setDisplayCondition(field.id, next),
1651
- translate
2175
+ translate,
2176
+ components
1652
2177
  }
1653
2178
  )
1654
2179
  ] }) : null
@@ -1656,11 +2181,10 @@ function FormBuilder({
1656
2181
  ] }, field.id);
1657
2182
  }) }),
1658
2183
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1659
- "button",
2184
+ Button,
1660
2185
  {
1661
2186
  className: "form-engine-builder__add",
1662
- type: "button",
1663
- "data-builder-action": "addField",
2187
+ action: "addField",
1664
2188
  disabled: initialFieldType === null || maxFieldsReached,
1665
2189
  onClick: addField,
1666
2190
  children: translate("builder.addQuestion")
@@ -1668,7 +2192,7 @@ function FormBuilder({
1668
2192
  )
1669
2193
  ] })
1670
2194
  }
1671
- );
2195
+ ) });
1672
2196
  }
1673
2197
 
1674
2198
  // src/context.tsx