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