@form-engine-ts/react 2.2.0 → 2.3.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,260 @@ 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
+ value,
722
+ onChange,
723
+ placeholder,
724
+ maxLength,
725
+ inputMode,
726
+ type = "text",
727
+ min,
728
+ max,
729
+ step
730
+ }) {
731
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
732
+ "input",
733
+ {
734
+ id,
735
+ className,
736
+ disabled,
737
+ readOnly,
738
+ "aria-label": ariaLabel,
739
+ type: type === "text" ? void 0 : type,
740
+ inputMode,
741
+ min,
742
+ max,
743
+ step,
744
+ value,
745
+ placeholder,
746
+ maxLength,
747
+ onChange: (event) => onChange(event.currentTarget.value)
748
+ }
749
+ );
750
+ }
751
+ function DefaultTextArea({
752
+ id,
753
+ className,
754
+ disabled,
755
+ readOnly,
756
+ "aria-label": ariaLabel,
757
+ value,
758
+ onChange,
759
+ rows,
760
+ placeholder,
761
+ maxLength
762
+ }) {
763
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
764
+ "textarea",
765
+ {
766
+ id,
767
+ className,
768
+ disabled,
769
+ readOnly,
770
+ "aria-label": ariaLabel,
771
+ value,
772
+ rows,
773
+ placeholder,
774
+ maxLength,
775
+ onChange: (event) => onChange(event.currentTarget.value)
776
+ }
777
+ );
778
+ }
779
+ function DefaultSelect({
780
+ id,
781
+ className,
782
+ disabled,
783
+ "aria-label": ariaLabel,
784
+ value,
785
+ onChange,
786
+ options
787
+ }) {
788
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
789
+ "select",
790
+ {
791
+ id,
792
+ className,
793
+ disabled,
794
+ "aria-label": ariaLabel,
795
+ value,
796
+ onChange: (event) => onChange(event.currentTarget.value),
797
+ children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value))
798
+ }
799
+ );
800
+ }
801
+ function DefaultCheckbox({
802
+ id,
803
+ className,
804
+ disabled,
805
+ "aria-label": ariaLabel,
806
+ checked,
807
+ onChange,
808
+ label
809
+ }) {
810
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className, children: [
811
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
812
+ "input",
813
+ {
814
+ id,
815
+ type: "checkbox",
816
+ disabled,
817
+ "aria-label": ariaLabel,
818
+ checked,
819
+ onChange: (event) => onChange(event.currentTarget.checked)
820
+ }
821
+ ),
822
+ label
823
+ ] });
824
+ }
825
+ function DefaultSection({
826
+ id,
827
+ className,
828
+ title,
829
+ description,
830
+ headingId,
831
+ "aria-label": ariaLabel,
832
+ onClickCapture,
833
+ children
834
+ }) {
835
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
836
+ "section",
837
+ {
838
+ id,
839
+ className,
840
+ "aria-label": ariaLabel,
841
+ "aria-labelledby": title === void 0 ? void 0 : headingId,
842
+ onClickCapture,
843
+ children: [
844
+ title === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: headingId, children: title }),
845
+ description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: description }),
846
+ children
847
+ ]
848
+ }
849
+ );
850
+ }
851
+ function DefaultFieldset({ className, legend, disabled, children }) {
852
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { className, disabled, children: [
853
+ legend === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("legend", { children: legend }),
854
+ children
855
+ ] });
856
+ }
857
+ function DefaultErrorMessage({ message }) {
858
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "form-engine-builder__error", children: message });
859
+ }
860
+ var DEFAULT_COMPONENTS = {
861
+ Button: DefaultButton,
862
+ IconButton: DefaultIconButton,
863
+ TextInput: DefaultTextInput,
864
+ TextArea: DefaultTextArea,
865
+ Select: DefaultSelect,
866
+ Checkbox: DefaultCheckbox,
867
+ Section: DefaultSection,
868
+ Fieldset: DefaultFieldset,
869
+ ErrorMessage: DefaultErrorMessage
870
+ };
871
+ var BuilderPrimitiveContext = (0, import_react2.createContext)({
872
+ components: DEFAULT_COMPONENTS,
873
+ readOnly: false
874
+ });
875
+ function BuilderButton(props) {
876
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
877
+ const Component = context.components.Button;
878
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
879
+ }
880
+ function BuilderIconButton(props) {
881
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
882
+ const Component = context.components.IconButton;
883
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
884
+ }
885
+ function BuilderTextInput(props) {
886
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
887
+ const Component = context.components.TextInput;
888
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
889
+ }
890
+ function BuilderTextArea(props) {
891
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
892
+ const Component = context.components.TextArea;
893
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
894
+ }
895
+ function BuilderSelect(props) {
896
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
897
+ const Component = context.components.Select;
898
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
899
+ }
900
+ function BuilderCheckbox(props) {
901
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
902
+ const Component = context.components.Checkbox;
903
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true, readOnly: context.readOnly });
904
+ }
905
+ function BuilderSection(props) {
906
+ const Component = (0, import_react2.useContext)(BuilderPrimitiveContext).components.Section;
907
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props });
908
+ }
909
+ function BuilderFieldset(props) {
910
+ const context = (0, import_react2.useContext)(BuilderPrimitiveContext);
911
+ const Component = context.components.Fieldset;
912
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props, disabled: context.readOnly || props.disabled === true });
913
+ }
914
+ function BuilderErrorMessage(props) {
915
+ const Component = (0, import_react2.useContext)(BuilderPrimitiveContext).components.ErrorMessage;
916
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props });
917
+ }
918
+ var GUARDED_COMPONENTS = {
919
+ Button: BuilderButton,
920
+ IconButton: BuilderIconButton,
921
+ TextInput: BuilderTextInput,
922
+ TextArea: BuilderTextArea,
923
+ Select: BuilderSelect,
924
+ Checkbox: BuilderCheckbox,
925
+ Section: BuilderSection,
926
+ Fieldset: BuilderFieldset,
927
+ ErrorMessage: BuilderErrorMessage
928
+ };
673
929
  var FIELD_TYPES = [
674
930
  "text",
675
931
  "textarea",
@@ -768,37 +1024,52 @@ function ConditionValueEditor({
768
1024
  source,
769
1025
  condition,
770
1026
  onChange,
771
- translate
1027
+ translate,
1028
+ components
772
1029
  }) {
1030
+ const { Select, TextInput } = components;
773
1031
  if (condition.operator === "not_empty") return null;
774
1032
  const update = (value) => onChange({ ...condition, value });
775
1033
  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
- ] });
1034
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1035
+ Select,
1036
+ {
1037
+ value: String(condition.value),
1038
+ onChange: (value) => update(value === "true"),
1039
+ options: [
1040
+ { value: "true", label: translate("builder.conditionTrue") },
1041
+ { value: "false", label: translate("builder.conditionFalse") }
1042
+ ]
1043
+ }
1044
+ );
780
1045
  }
781
1046
  if (source.type === "number" || source.type === "rating") {
782
1047
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
783
- "input",
1048
+ TextInput,
784
1049
  {
785
1050
  "aria-label": translate("builder.conditionValue"),
786
1051
  type: "number",
787
- value: typeof condition.value === "number" ? condition.value : "",
788
- onChange: (event) => update(event.currentTarget.value === "" ? 0 : event.currentTarget.valueAsNumber)
1052
+ value: typeof condition.value === "number" ? String(condition.value) : "",
1053
+ onChange: (value) => update(value === "" ? 0 : Number(value))
789
1054
  }
790
1055
  );
791
1056
  }
792
1057
  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)) });
1058
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1059
+ Select,
1060
+ {
1061
+ value: String(condition.value ?? ""),
1062
+ onChange: update,
1063
+ options: source.options.map((option) => ({ value: option.id, label: option.label }))
1064
+ }
1065
+ );
794
1066
  }
795
1067
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
796
- "input",
1068
+ TextInput,
797
1069
  {
798
1070
  "aria-label": translate("builder.conditionValue"),
799
- type: "text",
800
1071
  value: typeof condition.value === "string" ? condition.value : "",
801
- onChange: (event) => update(event.currentTarget.value)
1072
+ onChange: update
802
1073
  }
803
1074
  );
804
1075
  }
@@ -826,8 +1097,19 @@ function FormBuilder({
826
1097
  onActionError,
827
1098
  createManualTranslationMetadata,
828
1099
  readOnly = false,
829
- features
1100
+ features,
1101
+ components: componentOverrides,
1102
+ slots
830
1103
  }) {
1104
+ const resolvedComponents = { ...DEFAULT_COMPONENTS, ...componentOverrides };
1105
+ const components = GUARDED_COMPONENTS;
1106
+ const { Button, Checkbox, ErrorMessage, Fieldset, IconButton, Section, Select, TextInput } = components;
1107
+ const ToolbarSlot = slots?.toolbar;
1108
+ const FieldEditorSlot = slots?.fieldEditor;
1109
+ const OptionEditorSlot = slots?.optionEditor;
1110
+ const PagesSlot = slots?.pages;
1111
+ const LocalizationSlot = slots?.localization;
1112
+ const TranslationActionsSlot = slots?.translationActions;
831
1113
  const headless = useFormBuilder({
832
1114
  schema,
833
1115
  onChange,
@@ -950,9 +1232,11 @@ function FormBuilder({
950
1232
  setIsTranslating(true);
951
1233
  setTranslationError(null);
952
1234
  try {
1235
+ const translationPolicy = policy ?? translationOptions?.policy;
953
1236
  const populated = await (0, import_core2.populateSchemaTranslations)(schema, [editingLocale], translationAdapter, {
954
1237
  overwrite: "missing-only",
955
- ...translationOptions
1238
+ ...translationOptions,
1239
+ ...translationPolicy === void 0 ? {} : { policy: translationPolicy }
956
1240
  });
957
1241
  onChange(populated.schema);
958
1242
  onTranslationReport?.(populated.report);
@@ -1025,8 +1309,81 @@ function FormBuilder({
1025
1309
  ]);
1026
1310
  const availableAllowedLocales = policy?.allowedLocales?.filter((candidate) => !registeredLocales.has(candidate));
1027
1311
  const localeLimitReached = policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales;
1028
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1029
- "section",
1312
+ const actions = {
1313
+ addField: (type, pageId) => executeAction(() => headless.addField(type, pageId), {
1314
+ action: "addField",
1315
+ ...pageId === void 0 ? { params: { type } } : { targetId: pageId, params: { type, pageId } }
1316
+ }),
1317
+ removeField: (fieldId) => executeAction(() => headless.removeField(fieldId), { action: "removeField", targetId: fieldId }),
1318
+ moveField: (fieldId, targetIndex) => executeAction(() => headless.moveField(fieldId, targetIndex), {
1319
+ action: "moveField",
1320
+ targetId: fieldId,
1321
+ params: { targetIndex }
1322
+ }),
1323
+ updateField: (fieldId, updater) => executeAction(() => headless.updateField(fieldId, updater), { action: "updateField", targetId: fieldId }),
1324
+ changeFieldType: (fieldId, type) => executeAction(() => headless.changeFieldType(fieldId, type), {
1325
+ action: "changeFieldType",
1326
+ targetId: fieldId,
1327
+ params: { type }
1328
+ }),
1329
+ addOption: (fieldId) => executeAction(() => headless.addOption(fieldId), { action: "addOption", targetId: fieldId }),
1330
+ updateOption: (fieldId, optionId, updater) => executeAction(() => headless.updateOption(fieldId, optionId, updater), {
1331
+ action: "updateOption",
1332
+ targetId: optionId,
1333
+ params: { fieldId }
1334
+ }),
1335
+ removeOption: (fieldId, optionId) => executeAction(() => headless.removeOption(fieldId, optionId), {
1336
+ action: "removeOption",
1337
+ targetId: optionId,
1338
+ params: { fieldId }
1339
+ }),
1340
+ moveOption: (fieldId, optionId, targetIndex) => executeAction(() => headless.moveOption(fieldId, optionId, targetIndex), {
1341
+ action: "moveOption",
1342
+ targetId: optionId,
1343
+ params: { fieldId, targetIndex }
1344
+ }),
1345
+ addPage: (questionId) => executeAction(() => headless.addPage(questionId), {
1346
+ action: "addPage",
1347
+ ...questionId === void 0 ? {} : { targetId: questionId, params: { questionId } }
1348
+ }),
1349
+ updatePage: (pageId, updater) => executeAction(() => headless.updatePage(pageId, updater), { action: "updatePage", targetId: pageId }),
1350
+ removePage: (pageId) => executeAction(() => headless.removePage(pageId), { action: "removePage", targetId: pageId }),
1351
+ movePage: (pageId, targetIndex) => executeAction(() => headless.movePage(pageId, targetIndex), {
1352
+ action: "movePage",
1353
+ targetId: pageId,
1354
+ params: { targetIndex }
1355
+ }),
1356
+ assignFieldToPage: (fieldId, pageId) => executeAction(() => headless.assignFieldToPage(fieldId, pageId), {
1357
+ action: "assignFieldToPage",
1358
+ targetId: fieldId,
1359
+ params: { pageId }
1360
+ }),
1361
+ setDisplayCondition: (fieldId, condition) => executeAction(() => headless.setDisplayCondition(fieldId, condition), {
1362
+ action: "setDisplayCondition",
1363
+ targetId: fieldId,
1364
+ ...condition === void 0 ? {} : { params: { condition } }
1365
+ }),
1366
+ setSourceText: (target, property, text) => executeAction(() => headless.setSourceText(target, property, text), {
1367
+ action: "setSourceText",
1368
+ ...target.id === void 0 ? {} : { targetId: target.id },
1369
+ params: { property, text }
1370
+ }),
1371
+ setLocaleTranslation: (targetLocale, target, property, text, options) => executeAction(() => headless.setLocaleTranslation(targetLocale, target, property, text, options), {
1372
+ action: "setLocaleTranslation",
1373
+ ...target.id === void 0 ? {} : { targetId: target.id },
1374
+ params: { locale: targetLocale, property }
1375
+ }),
1376
+ addLocale: (targetLocale) => executeAction(() => headless.addLocale(targetLocale), {
1377
+ action: "addLocale",
1378
+ params: { locale: targetLocale }
1379
+ }),
1380
+ setDefaultLocale: (targetLocale) => executeAction(() => headless.setDefaultLocale(targetLocale), {
1381
+ action: "setDefaultLocale",
1382
+ params: { locale: targetLocale }
1383
+ })
1384
+ };
1385
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderPrimitiveContext.Provider, { value: { components: resolvedComponents, readOnly }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1386
+ Section,
1030
1387
  {
1031
1388
  className: `form-engine-builder ${className}`.trim(),
1032
1389
  "aria-label": translate("builder.formBuilder"),
@@ -1045,362 +1402,451 @@ function FormBuilder({
1045
1402
  addOption(fieldId);
1046
1403
  }
1047
1404
  },
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: [
1405
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Fieldset, { className: "form-engine-builder__controls", disabled: readOnly, children: [
1406
+ pagesEnabled ? PagesSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1407
+ Section,
1408
+ {
1409
+ className: "form-engine-builder__pages",
1410
+ headingId: "builder-pages-heading",
1411
+ title: translate("builder.pages"),
1412
+ 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: [
1413
+ schema.pages.map((page, pageIndex) => {
1414
+ const priorQuestionIds = new Set(
1415
+ schema.pages?.slice(0, pageIndex).flatMap((item) => item.questionIds)
1416
+ );
1417
+ const availableSources = schema.fields.filter((field) => priorQuestionIds.has(field.id));
1418
+ const source = schema.fields.find((field) => field.id === page.displayCondition?.questionId);
1419
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1420
+ Fieldset,
1421
+ {
1422
+ className: "form-engine-builder__page",
1423
+ legend: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}`,
1424
+ children: [
1425
+ /* @__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: [
1426
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1427
+ IconButton,
1428
+ {
1429
+ icon: "\u2191",
1430
+ title: translate("builder.moveUp", { title: page.title ?? page.id }),
1431
+ disabled: pageIndex === 0,
1432
+ onClick: () => movePage(pageIndex, -1)
1433
+ }
1434
+ ),
1435
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1436
+ IconButton,
1437
+ {
1438
+ icon: "\u2193",
1439
+ title: translate("builder.moveDown", { title: page.title ?? page.id }),
1440
+ disabled: pageIndex === (schema.pages?.length ?? 0) - 1,
1441
+ onClick: () => movePage(pageIndex, 1)
1442
+ }
1443
+ ),
1444
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { onClick: () => removePage(pageIndex), variant: "danger", children: translate("builder.deleteAction") })
1445
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1446
+ ToolbarSlot,
1447
+ {
1448
+ schema,
1449
+ kind: "page",
1450
+ targetId: page.id,
1451
+ index: pageIndex,
1452
+ total: schema.pages?.length ?? 0,
1453
+ title: page.title ?? page.id,
1454
+ onMoveUp: () => movePage(pageIndex, -1),
1455
+ onMoveDown: () => movePage(pageIndex, 1),
1456
+ onRemove: () => removePage(pageIndex),
1457
+ readOnly,
1458
+ actions,
1459
+ components
1460
+ }
1461
+ ) }),
1462
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1463
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1464
+ translate("builder.pageTitle"),
1465
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1466
+ TextInput,
1467
+ {
1468
+ value: page.title ?? "",
1469
+ onChange: (value) => {
1470
+ updatePage(page.id, (current) => {
1471
+ if (value.length > 0) return { ...current, title: value };
1472
+ const { title: _title, ...withoutTitle } = current;
1473
+ return withoutTitle;
1474
+ });
1475
+ }
1476
+ }
1477
+ )
1478
+ ] }),
1479
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1480
+ translate("builder.pageDescription"),
1481
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1482
+ TextInput,
1483
+ {
1484
+ value: page.description ?? "",
1485
+ onChange: (value) => {
1486
+ updatePage(page.id, (current) => {
1487
+ if (value.length > 0) return { ...current, description: value };
1488
+ const { description: _description, ...withoutDescription } = current;
1489
+ return withoutDescription;
1490
+ });
1491
+ }
1492
+ }
1493
+ )
1494
+ ] })
1495
+ ] }),
1496
+ !localizationEnabled || editingLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__translation-editor", children: [
1497
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: editingLocale }),
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.translations?.[editingLocale]?.title ?? "",
1505
+ onChange: (value) => updateManualTranslation({
1506
+ locale: editingLocale,
1507
+ kind: "page",
1508
+ nodeId: page.id,
1509
+ property: "title",
1510
+ sourceText: page.title ?? "",
1511
+ translatedText: value,
1512
+ ...page.translationMetadata?.[editingLocale]?.title === void 0 ? {} : {
1513
+ existingTranslationMetadata: page.translationMetadata[editingLocale]?.title
1514
+ }
1515
+ })
1516
+ }
1517
+ )
1518
+ ] }),
1519
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1520
+ translate("builder.pageDescription"),
1521
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1522
+ TextInput,
1523
+ {
1524
+ value: page.translations?.[editingLocale]?.description ?? "",
1525
+ onChange: (value) => updateManualTranslation({
1526
+ locale: editingLocale,
1527
+ kind: "page",
1528
+ nodeId: page.id,
1529
+ property: "description",
1530
+ sourceText: page.description ?? "",
1531
+ translatedText: value,
1532
+ ...page.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
1533
+ existingTranslationMetadata: page.translationMetadata[editingLocale]?.description
1534
+ }
1535
+ })
1536
+ }
1537
+ )
1538
+ ] })
1539
+ ] })
1540
+ ] }),
1541
+ conditionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__condition", children: [
1542
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1543
+ translate("builder.pageCondition"),
1544
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1545
+ Select,
1546
+ {
1547
+ value: page.displayCondition?.questionId ?? "",
1548
+ onChange: (value) => {
1549
+ const selected = schema.fields.find((field) => field.id === value);
1550
+ updatePage(page.id, (current) => {
1551
+ if (selected === void 0) {
1552
+ const { displayCondition: _condition, ...withoutCondition } = current;
1553
+ return withoutCondition;
1554
+ }
1555
+ return {
1556
+ ...current,
1557
+ displayCondition: conditionWithValue(
1558
+ selected.id,
1559
+ conditionOperators(selected)[0] ?? "not_empty",
1560
+ defaultConditionValue(selected)
1561
+ )
1562
+ };
1563
+ });
1564
+ },
1565
+ options: [
1566
+ { value: "", label: translate("builder.alwaysVisible") },
1567
+ ...availableSources.map((field) => ({ value: field.id, label: field.title }))
1568
+ ]
1569
+ }
1570
+ )
1571
+ ] }),
1572
+ page.displayCondition !== void 0 && source !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1573
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1574
+ Select,
1575
+ {
1576
+ "aria-label": translate("builder.conditionOperator"),
1577
+ value: page.displayCondition.operator,
1578
+ onChange: (value) => {
1579
+ const operator = value;
1580
+ updatePage(page.id, (current) => ({
1581
+ ...current,
1582
+ displayCondition: conditionWithValue(
1583
+ source.id,
1584
+ operator,
1585
+ defaultConditionValue(source)
1586
+ )
1587
+ }));
1588
+ },
1589
+ options: conditionOperators(source).map((operator) => ({
1590
+ value: operator,
1591
+ label: translate(operatorKey(operator))
1592
+ }))
1593
+ }
1594
+ ),
1595
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1596
+ ConditionValueEditor,
1597
+ {
1598
+ source,
1599
+ condition: page.displayCondition,
1600
+ onChange: (condition) => updatePage(page.id, (current) => ({ ...current, displayCondition: condition })),
1601
+ translate,
1602
+ components
1603
+ }
1604
+ )
1605
+ ] }) : null
1606
+ ] }) : null
1607
+ ]
1608
+ },
1609
+ page.id
1610
+ );
1611
+ }),
1612
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__page-add", children: [
1613
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1614
+ translate("builder.pageQuestion"),
1061
1615
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1062
- "button",
1616
+ Select,
1063
1617
  {
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"
1618
+ value: newPageQuestionId,
1619
+ disabled: movablePageQuestions.length === 0,
1620
+ onChange: setNewPageQuestionId,
1621
+ options: [
1622
+ { value: "", label: "\u2014" },
1623
+ ...schema.fields.filter((field) => movablePageQuestions.includes(field.id)).map((field) => ({ value: field.id, label: field.title }))
1624
+ ]
1069
1625
  }
1070
- ),
1071
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1072
- "button",
1626
+ )
1627
+ ] }),
1628
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { disabled: movablePageQuestions.length === 0, onClick: addPage, children: translate("builder.addPage") })
1629
+ ] })
1630
+ ] })
1631
+ }
1632
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1633
+ PagesSlot,
1634
+ {
1635
+ schema,
1636
+ currentLocale: editingLocale,
1637
+ readOnly,
1638
+ actions,
1639
+ components
1640
+ }
1641
+ ) : null,
1642
+ localizationEnabled ? LocalizationSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1643
+ Section,
1644
+ {
1645
+ className: "form-engine-builder__localization",
1646
+ headingId: "builder-localization-heading",
1647
+ title: translate("builder.localization"),
1648
+ children: [
1649
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1650
+ translate("builder.completionMessage"),
1651
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1652
+ TextInput,
1653
+ {
1654
+ value: schema.completionMessage ?? "",
1655
+ onChange: (value) => setSourceText({ kind: "form" }, "completionMessage", value)
1656
+ }
1657
+ )
1658
+ ] }),
1659
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1660
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1661
+ translate("builder.defaultLocale"),
1662
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextInput, { value: schema.defaultLocale ?? "", onChange: setDefaultLocale })
1663
+ ] }),
1664
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { htmlFor: "builder-new-locale", children: [
1665
+ translate("builder.addLocale"),
1666
+ availableAllowedLocales === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextInput, { id: "builder-new-locale", value: newLocale, onChange: setNewLocale }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1667
+ Select,
1073
1668
  {
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"
1669
+ id: "builder-new-locale",
1670
+ value: newLocale,
1671
+ onChange: setNewLocale,
1672
+ options: [
1673
+ { value: "", label: "\u2014" },
1674
+ ...availableAllowedLocales.map((candidate) => ({ value: candidate, label: candidate }))
1675
+ ]
1079
1676
  }
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
- ] })
1677
+ )
1118
1678
  ] }),
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
- ] })
1679
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1680
+ Button,
1681
+ {
1682
+ action: "addLocale",
1683
+ disabled: newLocale.trim().length === 0 || localeLimitReached,
1684
+ onClick: addLocale,
1685
+ children: translate("builder.addLocale")
1686
+ }
1687
+ ),
1688
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1689
+ translate("builder.editLocale"),
1690
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1691
+ Select,
1692
+ {
1693
+ value: editingLocale,
1694
+ onChange: setEditingLocale,
1695
+ options: [
1696
+ { value: "", label: "\u2014" },
1697
+ ...(schema.supportedLocales ?? []).filter((item) => item !== schema.defaultLocale).map((item) => ({ value: item, label: item }))
1698
+ ]
1699
+ }
1700
+ )
1163
1701
  ] }),
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",
1702
+ TranslationActionsSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1703
+ Button,
1233
1704
  {
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
- ]
1705
+ disabled: translationAdapter === void 0 || editingLocale.length === 0 || isTranslating,
1706
+ onClick: () => void translateAll(),
1707
+ children: translate("builder.autoTranslate")
1708
+ }
1709
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1710
+ TranslationActionsSlot,
1711
+ {
1712
+ schema,
1713
+ currentLocale: editingLocale,
1714
+ onAutoTranslate: () => void translateAll(),
1715
+ isTranslating,
1716
+ readOnly,
1717
+ actions,
1718
+ components
1241
1719
  }
1242
1720
  )
1243
1721
  ] }),
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))
1722
+ translationAdapter === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: translate("builder.translationUnavailable") }) : null,
1723
+ translationError === null ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorMessage, { message: translationError }),
1724
+ editingLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1725
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1726
+ translate("builder.questionTitle"),
1727
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1728
+ TextInput,
1729
+ {
1730
+ value: schema.translations?.[editingLocale]?.title ?? "",
1731
+ onChange: (value) => updateFormTranslation("title", value)
1732
+ }
1733
+ )
1734
+ ] }),
1735
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1736
+ translate("builder.pageDescription"),
1737
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1738
+ TextInput,
1739
+ {
1740
+ value: schema.translations?.[editingLocale]?.description ?? "",
1741
+ onChange: (value) => updateFormTranslation("description", value)
1742
+ }
1743
+ )
1744
+ ] }),
1745
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1746
+ translate("builder.completionMessage"),
1747
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1748
+ TextInput,
1749
+ {
1750
+ value: schema.translations?.[editingLocale]?.completionMessage ?? "",
1751
+ onChange: (value) => updateFormTranslation("completionMessage", value)
1752
+ }
1753
+ )
1754
+ ] })
1308
1755
  ] })
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,
1756
+ ]
1757
+ }
1758
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1759
+ LocalizationSlot,
1760
+ {
1761
+ schema,
1762
+ currentLocale: editingLocale,
1763
+ onCurrentLocaleChange: setEditingLocale,
1764
+ onAutoTranslate: () => void translateAll(),
1765
+ isTranslating,
1766
+ ...translationError === null ? {} : { translationError },
1767
+ readOnly,
1768
+ actions,
1769
+ components
1770
+ }
1771
+ ) : null,
1355
1772
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "form-engine-builder__list", children: schema.fields.map((field, index) => {
1356
1773
  const condition = field.displayCondition;
1357
1774
  const source = condition === void 0 ? void 0 : schema.fields.find((item) => item.id === condition.questionId);
1358
1775
  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: [
1776
+ if (FieldEditorSlot !== void 0) {
1777
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1778
+ FieldEditorSlot,
1779
+ {
1780
+ schema,
1781
+ field,
1782
+ index,
1783
+ currentLocale: editingLocale,
1784
+ ...policy === void 0 ? {} : { policy },
1785
+ readOnly,
1786
+ actions,
1787
+ components
1788
+ },
1789
+ field.id
1790
+ );
1791
+ }
1792
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Fieldset, { className: "form-engine-builder__question", legend: field.title, children: [
1793
+ /* @__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
1794
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1363
- "button",
1795
+ IconButton,
1364
1796
  {
1365
- type: "button",
1797
+ icon: "\u2191",
1798
+ title: translate("builder.moveUp", { title: field.title }),
1366
1799
  disabled: index === 0,
1367
- onClick: () => moveField(index, -1),
1368
- "aria-label": translate("builder.moveUp", { title: field.title }),
1369
- children: "\u2191"
1800
+ onClick: () => moveField(index, -1)
1370
1801
  }
1371
1802
  ),
1372
1803
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1373
- "button",
1804
+ IconButton,
1374
1805
  {
1375
- type: "button",
1806
+ icon: "\u2193",
1807
+ title: translate("builder.moveDown", { title: field.title }),
1376
1808
  disabled: index === schema.fields.length - 1,
1377
- onClick: () => moveField(index, 1),
1378
- "aria-label": translate("builder.moveDown", { title: field.title }),
1379
- children: "\u2193"
1809
+ onClick: () => moveField(index, 1)
1380
1810
  }
1381
1811
  ),
1382
1812
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1383
- "button",
1813
+ Button,
1384
1814
  {
1385
- type: "button",
1386
1815
  disabled: schema.fields.length === 1,
1387
1816
  onClick: () => removeField(field.id),
1388
1817
  "aria-label": translate("builder.delete", { title: field.title }),
1818
+ variant: "danger",
1389
1819
  children: translate("builder.deleteAction")
1390
1820
  }
1391
1821
  )
1392
- ] }),
1822
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1823
+ ToolbarSlot,
1824
+ {
1825
+ schema,
1826
+ kind: "field",
1827
+ targetId: field.id,
1828
+ index,
1829
+ total: schema.fields.length,
1830
+ title: field.title,
1831
+ onMoveUp: () => moveField(index, -1),
1832
+ onMoveDown: () => moveField(index, 1),
1833
+ onRemove: () => removeField(field.id),
1834
+ readOnly,
1835
+ actions,
1836
+ components
1837
+ }
1838
+ ) }),
1393
1839
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__grid", children: [
1394
1840
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1395
1841
  translate("builder.questionTitle"),
1396
1842
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1397
- "input",
1843
+ TextInput,
1398
1844
  {
1399
1845
  value: field.title,
1400
1846
  placeholder: translate("builder.questionTitlePlaceholder"),
1401
- onChange: (event) => updateField(field.id, (current) => ({
1847
+ onChange: (value) => updateField(field.id, (current) => ({
1402
1848
  ...current,
1403
- title: event.currentTarget.value.trim().length === 0 ? current.title : event.currentTarget.value
1849
+ title: value.trim().length === 0 ? current.title : value
1404
1850
  }))
1405
1851
  }
1406
1852
  )
@@ -1408,36 +1854,37 @@ function FormBuilder({
1408
1854
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1409
1855
  translate("builder.type"),
1410
1856
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1411
- "select",
1857
+ Select,
1412
1858
  {
1413
1859
  value: field.type,
1414
- onChange: (event) => changeType(field.id, event.currentTarget.value),
1415
- children: FIELD_TYPES.filter(
1860
+ onChange: (value) => changeType(field.id, value),
1861
+ options: FIELD_TYPES.filter(
1416
1862
  (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))
1863
+ ).map((type) => ({ value: type, label: translate(fieldTypeKey(type)) }))
1418
1864
  }
1419
1865
  )
1420
1866
  ] }),
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
- ] })
1867
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1868
+ Checkbox,
1869
+ {
1870
+ className: "form-engine-builder__check",
1871
+ checked: field.required === true,
1872
+ onChange: (checked) => updateField(field.id, (current) => ({ ...current, required: checked })),
1873
+ label: translate("builder.required")
1874
+ }
1875
+ )
1432
1876
  ] }),
1433
1877
  !pagesEnabled || schema.pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1434
1878
  translate("builder.questionPage"),
1435
1879
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1436
- "select",
1880
+ Select,
1437
1881
  {
1438
1882
  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))
1883
+ onChange: (value) => assignFieldToPage(field.id, value),
1884
+ options: schema.pages.map((page, pageIndex) => ({
1885
+ value: page.id,
1886
+ label: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}`
1887
+ }))
1441
1888
  }
1442
1889
  )
1443
1890
  ] }),
@@ -1447,16 +1894,16 @@ function FormBuilder({
1447
1894
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1448
1895
  translate("builder.questionTitle"),
1449
1896
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1450
- "input",
1897
+ TextInput,
1451
1898
  {
1452
1899
  value: field.translations?.[editingLocale]?.title ?? "",
1453
- onChange: (event) => updateManualTranslation({
1900
+ onChange: (value) => updateManualTranslation({
1454
1901
  locale: editingLocale,
1455
1902
  kind: "field",
1456
1903
  nodeId: field.id,
1457
1904
  property: "title",
1458
1905
  sourceText: field.title,
1459
- translatedText: event.currentTarget.value,
1906
+ translatedText: value,
1460
1907
  ...field.translationMetadata?.[editingLocale]?.title === void 0 ? {} : {
1461
1908
  existingTranslationMetadata: field.translationMetadata[editingLocale]?.title
1462
1909
  }
@@ -1467,16 +1914,16 @@ function FormBuilder({
1467
1914
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1468
1915
  translate("builder.pageDescription"),
1469
1916
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1470
- "input",
1917
+ TextInput,
1471
1918
  {
1472
1919
  value: field.translations?.[editingLocale]?.description ?? "",
1473
- onChange: (event) => updateManualTranslation({
1920
+ onChange: (value) => updateManualTranslation({
1474
1921
  locale: editingLocale,
1475
1922
  kind: "field",
1476
1923
  nodeId: field.id,
1477
1924
  property: "description",
1478
1925
  sourceText: field.description ?? "",
1479
- translatedText: event.currentTarget.value,
1926
+ translatedText: value,
1480
1927
  ...field.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
1481
1928
  existingTranslationMetadata: field.translationMetadata[editingLocale]?.description
1482
1929
  }
@@ -1491,16 +1938,16 @@ function FormBuilder({
1491
1938
  editingLocale,
1492
1939
  ")",
1493
1940
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1494
- "input",
1941
+ TextInput,
1495
1942
  {
1496
1943
  value: option.translations?.[editingLocale] ?? "",
1497
- onChange: (event) => updateManualTranslation({
1944
+ onChange: (value) => updateManualTranslation({
1498
1945
  locale: editingLocale,
1499
1946
  kind: "option",
1500
1947
  nodeId: option.id,
1501
1948
  property: "label",
1502
1949
  sourceText: option.label,
1503
- translatedText: event.currentTarget.value,
1950
+ translatedText: value,
1504
1951
  ...option.translationMetadata?.[editingLocale]?.label === void 0 ? {} : {
1505
1952
  existingTranslationMetadata: option.translationMetadata[editingLocale]?.label
1506
1953
  }
@@ -1513,12 +1960,12 @@ function FormBuilder({
1513
1960
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1514
1961
  translate("builder.minimum"),
1515
1962
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1516
- "input",
1963
+ TextInput,
1517
1964
  {
1518
1965
  type: "number",
1519
- value: field.min ?? 1,
1520
- onChange: (event) => {
1521
- const min = event.currentTarget.valueAsNumber;
1966
+ value: String(field.min ?? 1),
1967
+ onChange: (value) => {
1968
+ const min = Number(value);
1522
1969
  if (!Number.isInteger(min)) return;
1523
1970
  updateField(
1524
1971
  field.id,
@@ -1531,12 +1978,12 @@ function FormBuilder({
1531
1978
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1532
1979
  translate("builder.maximum"),
1533
1980
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1534
- "input",
1981
+ TextInput,
1535
1982
  {
1536
1983
  type: "number",
1537
- value: field.max ?? 5,
1538
- onChange: (event) => {
1539
- const max = event.currentTarget.valueAsNumber;
1984
+ value: String(field.max ?? 5),
1985
+ onChange: (value) => {
1986
+ const max = Number(value);
1540
1987
  if (!Number.isInteger(max)) return;
1541
1988
  updateField(
1542
1989
  field.id,
@@ -1549,52 +1996,82 @@ function FormBuilder({
1549
1996
  ] }) : null,
1550
1997
  "options" in field ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__options", children: [
1551
1998
  /* @__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",
1999
+ field.options.map(
2000
+ (option, optionIndex) => OptionEditorSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__option", children: [
2001
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2002
+ TextInput,
2003
+ {
2004
+ "aria-label": translate("builder.optionLabel", { index: optionIndex + 1 }),
2005
+ value: option.label,
2006
+ placeholder: translate("builder.optionLabelPlaceholder"),
2007
+ onChange: (value) => value.trim().length === 0 ? void 0 : updateOption(field.id, option.id, value)
2008
+ }
2009
+ ),
2010
+ ToolbarSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2011
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2012
+ IconButton,
2013
+ {
2014
+ icon: "\u2191",
2015
+ title: translate("builder.moveUp", { title: option.label }),
2016
+ disabled: optionIndex === 0,
2017
+ onClick: () => moveOption(field.id, option.id, optionIndex - 1)
2018
+ }
2019
+ ),
2020
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2021
+ IconButton,
2022
+ {
2023
+ icon: "\u2193",
2024
+ title: translate("builder.moveDown", { title: option.label }),
2025
+ disabled: optionIndex === field.options.length - 1,
2026
+ onClick: () => moveOption(field.id, option.id, optionIndex + 1)
2027
+ }
2028
+ ),
2029
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2030
+ Button,
2031
+ {
2032
+ disabled: field.options.length === 1,
2033
+ onClick: () => removeOption(field.id, option.id),
2034
+ variant: "danger",
2035
+ children: translate("builder.remove")
2036
+ }
2037
+ )
2038
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2039
+ ToolbarSlot,
2040
+ {
2041
+ schema,
2042
+ kind: "option",
2043
+ targetId: option.id,
2044
+ index: optionIndex,
2045
+ total: field.options.length,
2046
+ title: option.label,
2047
+ onMoveUp: () => moveOption(field.id, option.id, optionIndex - 1),
2048
+ onMoveDown: () => moveOption(field.id, option.id, optionIndex + 1),
2049
+ onRemove: () => removeOption(field.id, option.id),
2050
+ readOnly,
2051
+ actions,
2052
+ components
2053
+ }
2054
+ )
2055
+ ] }, option.id) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2056
+ OptionEditorSlot,
1584
2057
  {
1585
- type: "button",
1586
- disabled: field.options.length === 1,
1587
- onClick: () => removeOption(field.id, option.id),
1588
- children: translate("builder.remove")
1589
- }
2058
+ schema,
2059
+ field,
2060
+ option,
2061
+ index: optionIndex,
2062
+ currentLocale: editingLocale,
2063
+ readOnly,
2064
+ actions,
2065
+ components
2066
+ },
2067
+ option.id
1590
2068
  )
1591
- ] }, option.id)),
2069
+ ),
1592
2070
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1593
- "button",
2071
+ Button,
1594
2072
  {
1595
- type: "button",
1596
- "data-builder-action": "addOption",
1597
- "data-target-id": field.id,
2073
+ action: "addOption",
2074
+ targetId: field.id,
1598
2075
  disabled: policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
1599
2076
  onClick: () => addOption(field.id),
1600
2077
  children: translate("builder.addOption")
@@ -1604,12 +2081,12 @@ function FormBuilder({
1604
2081
  conditionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "form-engine-builder__condition", children: [
1605
2082
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1606
2083
  translate("builder.displayCondition"),
1607
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1608
- "select",
2084
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2085
+ Select,
1609
2086
  {
1610
2087
  value: condition?.questionId ?? "",
1611
- onChange: (event) => {
1612
- const selected = schema.fields.find((item) => item.id === event.currentTarget.value);
2088
+ onChange: (value) => {
2089
+ const selected = schema.fields.find((item) => item.id === value);
1613
2090
  setDisplayCondition(
1614
2091
  field.id,
1615
2092
  selected === void 0 ? void 0 : conditionWithValue(
@@ -1619,27 +2096,30 @@ function FormBuilder({
1619
2096
  )
1620
2097
  );
1621
2098
  },
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))
2099
+ options: [
2100
+ { value: "", label: translate("builder.alwaysVisible") },
2101
+ ...availableSources.map((candidate) => ({ value: candidate.id, label: candidate.title }))
1625
2102
  ]
1626
2103
  }
1627
2104
  )
1628
2105
  ] }),
1629
2106
  condition !== void 0 && source !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1630
2107
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1631
- "select",
2108
+ Select,
1632
2109
  {
1633
2110
  "aria-label": translate("builder.conditionOperator"),
1634
2111
  value: condition.operator,
1635
- onChange: (event) => {
1636
- const operator = event.currentTarget.value;
2112
+ onChange: (value) => {
2113
+ const operator = value;
1637
2114
  setDisplayCondition(
1638
2115
  field.id,
1639
2116
  conditionWithValue(source.id, operator, defaultConditionValue(source))
1640
2117
  );
1641
2118
  },
1642
- children: conditionOperators(source).map((operator) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: operator, children: translate(operatorKey(operator)) }, operator))
2119
+ options: conditionOperators(source).map((operator) => ({
2120
+ value: operator,
2121
+ label: translate(operatorKey(operator))
2122
+ }))
1643
2123
  }
1644
2124
  ),
1645
2125
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1648,7 +2128,8 @@ function FormBuilder({
1648
2128
  source,
1649
2129
  condition,
1650
2130
  onChange: (next) => setDisplayCondition(field.id, next),
1651
- translate
2131
+ translate,
2132
+ components
1652
2133
  }
1653
2134
  )
1654
2135
  ] }) : null
@@ -1656,11 +2137,10 @@ function FormBuilder({
1656
2137
  ] }, field.id);
1657
2138
  }) }),
1658
2139
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1659
- "button",
2140
+ Button,
1660
2141
  {
1661
2142
  className: "form-engine-builder__add",
1662
- type: "button",
1663
- "data-builder-action": "addField",
2143
+ action: "addField",
1664
2144
  disabled: initialFieldType === null || maxFieldsReached,
1665
2145
  onClick: addField,
1666
2146
  children: translate("builder.addQuestion")
@@ -1668,7 +2148,7 @@ function FormBuilder({
1668
2148
  )
1669
2149
  ] })
1670
2150
  }
1671
- );
2151
+ ) });
1672
2152
  }
1673
2153
 
1674
2154
  // src/context.tsx