@form-engine-ts/react 2.9.2 → 2.9.4

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
@@ -984,24 +984,39 @@ function DefaultCheckbox({
984
984
  id,
985
985
  className,
986
986
  disabled,
987
+ readOnly,
987
988
  "aria-label": ariaLabel,
989
+ "aria-describedby": ariaDescribedBy,
990
+ "aria-labelledby": ariaLabelledBy,
991
+ name,
992
+ required,
993
+ error,
994
+ helperText,
988
995
  checked,
989
996
  onChange,
990
997
  label
991
998
  }) {
992
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className, children: [
993
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
994
- "input",
995
- {
996
- id,
997
- type: "checkbox",
998
- disabled,
999
- "aria-label": ariaLabel,
1000
- checked,
1001
- onChange: (event) => onChange(event.currentTarget.checked)
1002
- }
1003
- ),
1004
- label
999
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1000
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className, children: [
1001
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1002
+ "input",
1003
+ {
1004
+ id,
1005
+ name,
1006
+ type: "checkbox",
1007
+ disabled: disabled || readOnly,
1008
+ required,
1009
+ "aria-label": ariaLabel,
1010
+ "aria-describedby": ariaDescribedBy,
1011
+ "aria-labelledby": ariaLabelledBy,
1012
+ "aria-invalid": error === true ? true : void 0,
1013
+ checked,
1014
+ onChange: (event) => onChange(event.currentTarget.checked)
1015
+ }
1016
+ ),
1017
+ label
1018
+ ] }),
1019
+ helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { id: ariaDescribedBy, children: helperText })
1005
1020
  ] });
1006
1021
  }
1007
1022
  function DefaultSection({
@@ -1184,6 +1199,7 @@ var BUILDER_DEFAULTS = {
1184
1199
  "builder.basicSettings": "Basic settings",
1185
1200
  "builder.formTitle": "Form title",
1186
1201
  "builder.formDescription": "Form description",
1202
+ "builder.description": "Description",
1187
1203
  "builder.moveUp": "Move {{title}} up",
1188
1204
  "builder.moveDown": "Move {{title}} down",
1189
1205
  "builder.delete": "Delete {{title}}",
@@ -1218,12 +1234,31 @@ var BUILDER_DEFAULTS = {
1218
1234
  "builder.pageQuestion": "Question to move to the new page",
1219
1235
  "builder.questionPage": "Page",
1220
1236
  "builder.pageCondition": "Page display condition",
1237
+ "builder.unassigned": "Unassigned",
1221
1238
  "builder.localization": "Localization",
1222
1239
  "builder.defaultLocale": "Default locale",
1223
1240
  "builder.supportedLocales": "Supported locales",
1224
1241
  "builder.addLocale": "Add locale",
1225
1242
  "builder.editLocale": "Edit locale",
1226
1243
  "builder.autoTranslate": "Translate all text",
1244
+ "builder.translating": "Translating\u2026",
1245
+ "builder.translationLocale": "Translation locale",
1246
+ "builder.selectLocale": "Select a locale to edit translations.",
1247
+ "builder.translation": "{{locale}} translation",
1248
+ "builder.translatedFormTitle": "Translated form title",
1249
+ "builder.translatedFormDescription": "Translated form description",
1250
+ "builder.translatedCompletionMessage": "Translated completion message",
1251
+ "builder.translatedQuestionTitle": "Translated question title",
1252
+ "builder.translatedDescription": "Translated description",
1253
+ "builder.actions.moveUp": "Move up",
1254
+ "builder.actions.moveDown": "Move down",
1255
+ "builder.actions.delete": "Delete",
1256
+ "builder.actions.add": "Add",
1257
+ "builder.actions.edit": "Edit",
1258
+ "builder.actions.settings": "Settings",
1259
+ "builder.actions.translate": "Translate",
1260
+ "builder.actions.close": "Close",
1261
+ "builder.actions.dragHandle": "Reorder",
1227
1262
  "builder.translationUnavailable": "Provide an async translation adapter to enable automatic translation.",
1228
1263
  "builder.fieldType.text": "Text",
1229
1264
  "builder.fieldType.textarea": "Textarea",
@@ -1244,6 +1279,22 @@ function interpolate(template, params) {
1244
1279
  (token, name) => Object.hasOwn(params, name) ? String(params[name]) : token
1245
1280
  );
1246
1281
  }
1282
+ function BuilderSectionGroup({ children }) {
1283
+ return children;
1284
+ }
1285
+ function sectionGroupName(node) {
1286
+ if (!(0, import_react2.isValidElement)(node) || node.type !== BuilderSectionGroup) return void 0;
1287
+ return node.props.name;
1288
+ }
1289
+ function OrderedBuilderSections({
1290
+ order,
1291
+ children
1292
+ }) {
1293
+ if (order === void 0) return children;
1294
+ const ranks = new Map(order.map((name, index) => [name, index]));
1295
+ const groups = import_react2.Children.toArray(children);
1296
+ return groups.map((group, index) => ({ group, index, rank: ranks.get(sectionGroupName(group) ?? "questions") ?? order.length })).sort((left, right) => left.rank - right.rank || left.index - right.index).map(({ group }) => group);
1297
+ }
1247
1298
  function fieldTypeKey(type) {
1248
1299
  return `builder.fieldType.${type}`;
1249
1300
  }
@@ -1346,6 +1397,7 @@ function FormBuilder({
1346
1397
  features,
1347
1398
  components: componentOverrides,
1348
1399
  slots,
1400
+ sectionOrder,
1349
1401
  disableDefaultStyles = false,
1350
1402
  unstyled = false
1351
1403
  }) {
@@ -1363,6 +1415,7 @@ function FormBuilder({
1363
1415
  const PagesSlot = slots?.pages;
1364
1416
  const LocalizationSlot = slots?.localization;
1365
1417
  const TranslationActionsSlot = slots?.translationActions;
1418
+ const resolvedSectionOrder = sectionOrder ?? slots?.sectionOrder;
1366
1419
  const headless = useFormBuilder({
1367
1420
  schema,
1368
1421
  onChange,
@@ -1377,7 +1430,11 @@ function FormBuilder({
1377
1430
  const [translationError, setTranslationError] = (0, import_react2.useState)(null);
1378
1431
  const [translationReport, setTranslationReport] = (0, import_react2.useState)();
1379
1432
  const translate = (key, params = {}) => {
1380
- const translated = translator?.translate(key, locale, params);
1433
+ const translatorParams = {};
1434
+ for (const [name, value] of Object.entries(params)) {
1435
+ if (typeof value === "string" || typeof value === "number") translatorParams[name] = value;
1436
+ }
1437
+ const translated = translator?.translate(key, locale, translatorParams);
1381
1438
  return translated === void 0 ? interpolate(BUILDER_DEFAULTS[key] ?? key, params) : translated;
1382
1439
  };
1383
1440
  const pagesEnabled = features?.pages ?? true;
@@ -1662,8 +1719,8 @@ function FormBuilder({
1662
1719
  addOption(fieldId);
1663
1720
  }
1664
1721
  },
1665
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Fieldset, { className: builderClass("form-engine-builder__controls"), disabled: readOnly, children: [
1666
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1722
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Fieldset, { className: builderClass("form-engine-builder__controls"), disabled: readOnly, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(OrderedBuilderSections, { ...resolvedSectionOrder === void 0 ? {} : { order: resolvedSectionOrder }, children: [
1723
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderSectionGroup, { name: "basicSettings", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1667
1724
  Section,
1668
1725
  {
1669
1726
  className: builderClass("form-engine-builder__basic-settings"),
@@ -1697,8 +1754,17 @@ function FormBuilder({
1697
1754
  ) })
1698
1755
  ] })
1699
1756
  }
1700
- ),
1701
- pagesEnabled ? PagesSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1757
+ ) }),
1758
+ resolvedSectionOrder === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderSectionGroup, { name: "completionMessage", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, { headingId: "builder-completion-message-heading", title: translate("builder.completionMessage"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1759
+ TextInput,
1760
+ {
1761
+ id: "builder-completion-message",
1762
+ label: translate("builder.completionMessage"),
1763
+ value: schema.completionMessage ?? "",
1764
+ onChange: (value) => setSourceText({ kind: "form" }, "completionMessage", value)
1765
+ }
1766
+ ) }) }),
1767
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderSectionGroup, { name: "questions", children: pagesEnabled ? PagesSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1702
1768
  Section,
1703
1769
  {
1704
1770
  className: builderClass("form-engine-builder__pages"),
@@ -1748,6 +1814,7 @@ function FormBuilder({
1748
1814
  ToolbarSlot,
1749
1815
  {
1750
1816
  schema,
1817
+ translate,
1751
1818
  kind: "page",
1752
1819
  targetId: page.id,
1753
1820
  index: pageIndex,
@@ -1894,7 +1961,10 @@ function FormBuilder({
1894
1961
  {
1895
1962
  source,
1896
1963
  condition: page.displayCondition,
1897
- onChange: (condition) => updatePage(page.id, (current) => ({ ...current, displayCondition: condition })),
1964
+ onChange: (condition) => updatePage(page.id, (current) => ({
1965
+ ...current,
1966
+ displayCondition: condition
1967
+ })),
1898
1968
  translate,
1899
1969
  components
1900
1970
  }
@@ -1929,20 +1999,22 @@ function FormBuilder({
1929
1999
  PagesSlot,
1930
2000
  {
1931
2001
  schema,
2002
+ translate,
1932
2003
  currentLocale: editingLocale,
2004
+ ...features === void 0 ? {} : { features },
1933
2005
  readOnly,
1934
2006
  actions,
1935
2007
  components
1936
2008
  }
1937
- ) : null,
1938
- localizationEnabled ? LocalizationSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2009
+ ) : null }),
2010
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderSectionGroup, { name: "localization", children: localizationEnabled ? LocalizationSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1939
2011
  Section,
1940
2012
  {
1941
2013
  className: builderClass("form-engine-builder__localization"),
1942
2014
  headingId: "builder-localization-heading",
1943
2015
  title: translate("builder.localization"),
1944
2016
  children: [
1945
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2017
+ resolvedSectionOrder === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1946
2018
  TextInput,
1947
2019
  {
1948
2020
  id: "builder-completion-message",
@@ -1950,7 +2022,7 @@ function FormBuilder({
1950
2022
  value: schema.completionMessage ?? "",
1951
2023
  onChange: (value) => setSourceText({ kind: "form" }, "completionMessage", value)
1952
2024
  }
1953
- ) }),
2025
+ ) }) : null,
1954
2026
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
1955
2027
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1956
2028
  TextInput,
@@ -2015,12 +2087,14 @@ function FormBuilder({
2015
2087
  TranslationActionsSlot,
2016
2088
  {
2017
2089
  schema,
2090
+ translate,
2018
2091
  currentLocale: editingLocale,
2019
2092
  onAutoTranslate: () => void translateAll(),
2020
2093
  isTranslating,
2021
2094
  ...translationError === null ? {} : { translationError },
2022
2095
  ...translationReport === void 0 ? {} : { translationReport },
2023
2096
  onClearTranslationError: () => setTranslationError(null),
2097
+ translationAdapterAvailable: translationAdapter !== void 0,
2024
2098
  readOnly,
2025
2099
  actions,
2026
2100
  components
@@ -2064,17 +2138,20 @@ function FormBuilder({
2064
2138
  LocalizationSlot,
2065
2139
  {
2066
2140
  schema,
2141
+ translate,
2067
2142
  currentLocale: editingLocale,
2068
2143
  onCurrentLocaleChange: setEditingLocale,
2069
2144
  onAutoTranslate: () => void translateAll(),
2070
2145
  isTranslating,
2071
2146
  ...translationError === null ? {} : { translationError },
2147
+ ...policy === void 0 ? {} : { policy },
2148
+ translationAdapterAvailable: translationAdapter !== void 0,
2072
2149
  readOnly,
2073
2150
  actions,
2074
2151
  components
2075
2152
  }
2076
- ) : null,
2077
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__list"), children: schema.fields.map((field, index) => {
2153
+ ) : null }),
2154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderSectionGroup, { name: "questions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__list"), children: schema.fields.map((field, index) => {
2078
2155
  const condition = field.displayCondition;
2079
2156
  const source = condition === void 0 ? void 0 : schema.fields.find((item) => item.id === condition.questionId);
2080
2157
  const availableSources = schema.fields.slice(0, index);
@@ -2086,7 +2163,9 @@ function FormBuilder({
2086
2163
  field,
2087
2164
  index,
2088
2165
  currentLocale: editingLocale,
2166
+ translate,
2089
2167
  ...policy === void 0 ? {} : { policy },
2168
+ ...features === void 0 ? {} : { features },
2090
2169
  readOnly,
2091
2170
  actions,
2092
2171
  components
@@ -2094,348 +2173,362 @@ function FormBuilder({
2094
2173
  field.id
2095
2174
  );
2096
2175
  }
2097
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Fieldset, { className: builderClass("form-engine-builder__question"), legend: field.title, children: [
2098
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__toolbar"), children: ToolbarSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2099
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2100
- IconButton,
2101
- {
2102
- actionType: "moveUp",
2103
- title: translate("builder.moveUp", { title: field.title }),
2104
- disabled: index === 0,
2105
- onClick: () => moveField(index, -1)
2106
- }
2107
- ),
2108
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2109
- IconButton,
2110
- {
2111
- actionType: "moveDown",
2112
- title: translate("builder.moveDown", { title: field.title }),
2113
- disabled: index === schema.fields.length - 1,
2114
- onClick: () => moveField(index, 1)
2115
- }
2116
- ),
2117
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2118
- IconButton,
2119
- {
2120
- actionType: "delete",
2121
- disabled: schema.fields.length === 1,
2122
- onClick: () => removeField(field.id),
2123
- "aria-label": translate("builder.delete", { title: field.title }),
2124
- title: translate("builder.delete", { title: field.title })
2125
- }
2126
- )
2127
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2128
- ToolbarSlot,
2129
- {
2130
- schema,
2131
- kind: "field",
2132
- targetId: field.id,
2133
- index,
2134
- total: schema.fields.length,
2135
- title: field.title,
2136
- onMoveUp: () => moveField(index, -1),
2137
- onMoveDown: () => moveField(index, 1),
2138
- onRemove: () => removeField(field.id),
2139
- readOnly,
2140
- actions,
2141
- components
2142
- }
2143
- ) }),
2144
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
2145
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2146
- TextInput,
2147
- {
2148
- id: `builder-field-${field.id}-title`,
2149
- name: `fields.${field.id}.title`,
2150
- label: translate("builder.questionTitle"),
2151
- required: true,
2152
- error: field.title.trim().length === 0,
2153
- helperText: field.title.trim().length === 0 ? translate("builder.required") : "",
2154
- "aria-describedby": field.title.trim().length === 0 ? `builder-field-${field.id}-title-error` : void 0,
2155
- value: field.title,
2156
- placeholder: translate("builder.questionTitlePlaceholder"),
2157
- onChange: (value) => updateField(field.id, (current) => ({
2158
- ...current,
2159
- title: value.trim().length === 0 ? current.title : value
2160
- }))
2161
- }
2162
- ) }),
2163
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2164
- Select,
2165
- {
2166
- id: `builder-field-${field.id}-type`,
2167
- label: translate("builder.type"),
2168
- value: field.type,
2169
- onChange: (value) => changeType(field.id, value),
2170
- options: FIELD_TYPES.filter(
2171
- (type) => policy?.allowedFieldTypes === void 0 || policy.allowedFieldTypes.includes(type)
2172
- ).map((type) => ({ value: type, label: translate(fieldTypeKey(type)) }))
2173
- }
2174
- ) }),
2175
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2176
- Checkbox,
2177
- {
2178
- className: builderClass("form-engine-builder__check"),
2179
- checked: field.required === true,
2180
- onChange: (checked) => updateField(field.id, (current) => ({ ...current, required: checked })),
2181
- label: translate("builder.required")
2182
- }
2183
- )
2184
- ] }),
2185
- !pagesEnabled || schema.pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2186
- Select,
2187
- {
2188
- id: `builder-field-${field.id}-page`,
2189
- label: translate("builder.questionPage"),
2190
- value: pageForField(field.id)?.id ?? "",
2191
- onChange: (value) => assignFieldToPage(field.id, value),
2192
- options: schema.pages.map((page, pageIndex) => ({
2193
- value: page.id,
2194
- label: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}`
2195
- }))
2196
- }
2197
- ) }),
2198
- !localizationEnabled || editingLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__translation-editor"), children: [
2199
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: editingLocale }),
2200
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
2201
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2202
- TextInput,
2176
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2177
+ Fieldset,
2178
+ {
2179
+ className: builderClass("form-engine-builder__question"),
2180
+ legend: field.title,
2181
+ children: [
2182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__toolbar"), children: ToolbarSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2184
+ IconButton,
2185
+ {
2186
+ actionType: "moveUp",
2187
+ title: translate("builder.moveUp", { title: field.title }),
2188
+ disabled: index === 0,
2189
+ onClick: () => moveField(index, -1)
2190
+ }
2191
+ ),
2192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2193
+ IconButton,
2194
+ {
2195
+ actionType: "moveDown",
2196
+ title: translate("builder.moveDown", { title: field.title }),
2197
+ disabled: index === schema.fields.length - 1,
2198
+ onClick: () => moveField(index, 1)
2199
+ }
2200
+ ),
2201
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2202
+ IconButton,
2203
+ {
2204
+ actionType: "delete",
2205
+ disabled: schema.fields.length === 1,
2206
+ onClick: () => removeField(field.id),
2207
+ "aria-label": translate("builder.delete", { title: field.title }),
2208
+ title: translate("builder.delete", { title: field.title })
2209
+ }
2210
+ )
2211
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2212
+ ToolbarSlot,
2203
2213
  {
2204
- id: `builder-field-${field.id}-${editingLocale}-title`,
2205
- label: translate("builder.questionTitle"),
2206
- value: field.translations?.[editingLocale]?.title ?? "",
2207
- onChange: (value) => updateManualTranslation({
2208
- locale: editingLocale,
2209
- kind: "field",
2210
- nodeId: field.id,
2211
- property: "title",
2212
- sourceText: field.title,
2213
- translatedText: value,
2214
- ...field.translationMetadata?.[editingLocale]?.title === void 0 ? {} : {
2215
- existingTranslationMetadata: field.translationMetadata[editingLocale]?.title
2216
- }
2217
- })
2214
+ schema,
2215
+ translate,
2216
+ kind: "field",
2217
+ targetId: field.id,
2218
+ index,
2219
+ total: schema.fields.length,
2220
+ title: field.title,
2221
+ onMoveUp: () => moveField(index, -1),
2222
+ onMoveDown: () => moveField(index, 1),
2223
+ onRemove: () => removeField(field.id),
2224
+ readOnly,
2225
+ actions,
2226
+ components
2218
2227
  }
2219
2228
  ) }),
2220
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2221
- TextInput,
2229
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
2230
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2231
+ TextInput,
2232
+ {
2233
+ id: `builder-field-${field.id}-title`,
2234
+ name: `fields.${field.id}.title`,
2235
+ label: translate("builder.questionTitle"),
2236
+ required: true,
2237
+ error: field.title.trim().length === 0,
2238
+ helperText: field.title.trim().length === 0 ? translate("builder.required") : "",
2239
+ "aria-describedby": field.title.trim().length === 0 ? `builder-field-${field.id}-title-error` : void 0,
2240
+ value: field.title,
2241
+ placeholder: translate("builder.questionTitlePlaceholder"),
2242
+ onChange: (value) => updateField(field.id, (current) => ({
2243
+ ...current,
2244
+ title: value.trim().length === 0 ? current.title : value
2245
+ }))
2246
+ }
2247
+ ) }),
2248
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2249
+ Select,
2250
+ {
2251
+ id: `builder-field-${field.id}-type`,
2252
+ label: translate("builder.type"),
2253
+ value: field.type,
2254
+ onChange: (value) => changeType(field.id, value),
2255
+ options: FIELD_TYPES.filter(
2256
+ (type) => policy?.allowedFieldTypes === void 0 || policy.allowedFieldTypes.includes(type)
2257
+ ).map((type) => ({ value: type, label: translate(fieldTypeKey(type)) }))
2258
+ }
2259
+ ) }),
2260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2261
+ Checkbox,
2262
+ {
2263
+ className: builderClass("form-engine-builder__check"),
2264
+ checked: field.required === true,
2265
+ onChange: (checked) => updateField(field.id, (current) => ({ ...current, required: checked })),
2266
+ label: translate("builder.required")
2267
+ }
2268
+ )
2269
+ ] }),
2270
+ !pagesEnabled || schema.pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2271
+ Select,
2222
2272
  {
2223
- id: `builder-field-${field.id}-${editingLocale}-description`,
2224
- label: translate("builder.pageDescription"),
2225
- value: field.translations?.[editingLocale]?.description ?? "",
2226
- onChange: (value) => updateManualTranslation({
2227
- locale: editingLocale,
2228
- kind: "field",
2229
- nodeId: field.id,
2230
- property: "description",
2231
- sourceText: field.description ?? "",
2232
- translatedText: value,
2233
- ...field.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
2234
- existingTranslationMetadata: field.translationMetadata[editingLocale]?.description
2235
- }
2236
- })
2273
+ id: `builder-field-${field.id}-page`,
2274
+ label: translate("builder.questionPage"),
2275
+ value: pageForField(field.id)?.id ?? "",
2276
+ onChange: (value) => assignFieldToPage(field.id, value),
2277
+ options: schema.pages.map((page, pageIndex) => ({
2278
+ value: page.id,
2279
+ label: page.title ?? `${translate("builder.newPage")} ${pageIndex + 1}`
2280
+ }))
2237
2281
  }
2238
- ) })
2239
- ] }),
2240
- "options" in field ? field.options.map((option, optionIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2241
- TextInput,
2242
- {
2243
- id: `builder-option-${option.id}-${editingLocale}`,
2244
- label: `${translate("builder.optionLabel", { index: optionIndex + 1 })} (${editingLocale})`,
2245
- value: option.translations?.[editingLocale] ?? "",
2246
- onChange: (value) => updateManualTranslation({
2247
- locale: editingLocale,
2248
- kind: "option",
2249
- nodeId: option.id,
2250
- property: "label",
2251
- sourceText: option.label,
2252
- translatedText: value,
2253
- ...option.translationMetadata?.[editingLocale]?.label === void 0 ? {} : {
2254
- existingTranslationMetadata: option.translationMetadata[editingLocale]?.label
2282
+ ) }),
2283
+ !localizationEnabled || editingLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__translation-editor"), children: [
2284
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: editingLocale }),
2285
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
2286
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2287
+ TextInput,
2288
+ {
2289
+ id: `builder-field-${field.id}-${editingLocale}-title`,
2290
+ label: translate("builder.questionTitle"),
2291
+ value: field.translations?.[editingLocale]?.title ?? "",
2292
+ onChange: (value) => updateManualTranslation({
2293
+ locale: editingLocale,
2294
+ kind: "field",
2295
+ nodeId: field.id,
2296
+ property: "title",
2297
+ sourceText: field.title,
2298
+ translatedText: value,
2299
+ ...field.translationMetadata?.[editingLocale]?.title === void 0 ? {} : {
2300
+ existingTranslationMetadata: field.translationMetadata[editingLocale]?.title
2301
+ }
2302
+ })
2303
+ }
2304
+ ) }),
2305
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2306
+ TextInput,
2307
+ {
2308
+ id: `builder-field-${field.id}-${editingLocale}-description`,
2309
+ label: translate("builder.pageDescription"),
2310
+ value: field.translations?.[editingLocale]?.description ?? "",
2311
+ onChange: (value) => updateManualTranslation({
2312
+ locale: editingLocale,
2313
+ kind: "field",
2314
+ nodeId: field.id,
2315
+ property: "description",
2316
+ sourceText: field.description ?? "",
2317
+ translatedText: value,
2318
+ ...field.translationMetadata?.[editingLocale]?.description === void 0 ? {} : {
2319
+ existingTranslationMetadata: field.translationMetadata[editingLocale]?.description
2320
+ }
2321
+ })
2322
+ }
2323
+ ) })
2324
+ ] }),
2325
+ "options" in field ? field.options.map((option, optionIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2326
+ TextInput,
2327
+ {
2328
+ id: `builder-option-${option.id}-${editingLocale}`,
2329
+ label: `${translate("builder.optionLabel", { index: optionIndex + 1 })} (${editingLocale})`,
2330
+ value: option.translations?.[editingLocale] ?? "",
2331
+ onChange: (value) => updateManualTranslation({
2332
+ locale: editingLocale,
2333
+ kind: "option",
2334
+ nodeId: option.id,
2335
+ property: "label",
2336
+ sourceText: option.label,
2337
+ translatedText: value,
2338
+ ...option.translationMetadata?.[editingLocale]?.label === void 0 ? {} : {
2339
+ existingTranslationMetadata: option.translationMetadata[editingLocale]?.label
2340
+ }
2341
+ })
2255
2342
  }
2256
- })
2257
- }
2258
- ) }, option.id)) : null
2259
- ] }),
2260
- field.type === "rating" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
2261
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2262
- TextInput,
2263
- {
2264
- id: `builder-field-${field.id}-minimum`,
2265
- label: translate("builder.minimum"),
2266
- type: "number",
2267
- value: String(field.min ?? 1),
2268
- onChange: (value) => {
2269
- const min = Number(value);
2270
- if (!Number.isInteger(min)) return;
2271
- updateField(
2272
- field.id,
2273
- (current) => current.type === "rating" ? { ...current, min, max: Math.max(min, current.max ?? 5) } : current
2274
- );
2275
- }
2276
- }
2277
- ) }),
2278
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2279
- TextInput,
2280
- {
2281
- id: `builder-field-${field.id}-maximum`,
2282
- label: translate("builder.maximum"),
2283
- type: "number",
2284
- value: String(field.max ?? 5),
2285
- onChange: (value) => {
2286
- const max = Number(value);
2287
- if (!Number.isInteger(max)) return;
2288
- updateField(
2289
- field.id,
2290
- (current) => current.type === "rating" ? { ...current, min: Math.min(current.min ?? 1, max), max } : current
2291
- );
2292
- }
2293
- }
2294
- ) })
2295
- ] }) : null,
2296
- "options" in field ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__options"), children: [
2297
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: translate("builder.options") }),
2298
- field.options.map(
2299
- (option, optionIndex) => OptionEditorSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__option"), children: [
2300
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2343
+ ) }, option.id)) : null
2344
+ ] }),
2345
+ field.type === "rating" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__grid"), children: [
2346
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2301
2347
  TextInput,
2302
2348
  {
2303
- id: `builder-option-${option.id}`,
2304
- label: translate("builder.optionLabel", { index: optionIndex + 1 }),
2305
- value: option.label,
2306
- placeholder: translate("builder.optionLabelPlaceholder"),
2307
- onChange: (value) => value.trim().length === 0 ? void 0 : updateOption(field.id, option.id, value)
2349
+ id: `builder-field-${field.id}-minimum`,
2350
+ label: translate("builder.minimum"),
2351
+ type: "number",
2352
+ value: String(field.min ?? 1),
2353
+ onChange: (value) => {
2354
+ const min = Number(value);
2355
+ if (!Number.isInteger(min)) return;
2356
+ updateField(
2357
+ field.id,
2358
+ (current) => current.type === "rating" ? { ...current, min, max: Math.max(min, current.max ?? 5) } : current
2359
+ );
2360
+ }
2308
2361
  }
2309
- ),
2310
- ToolbarSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2311
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2312
- IconButton,
2313
- {
2314
- actionType: "moveUp",
2315
- title: translate("builder.moveUp", { title: option.label }),
2316
- disabled: optionIndex === 0,
2317
- onClick: () => moveOption(field.id, option.id, optionIndex - 1)
2362
+ ) }),
2363
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2364
+ TextInput,
2365
+ {
2366
+ id: `builder-field-${field.id}-maximum`,
2367
+ label: translate("builder.maximum"),
2368
+ type: "number",
2369
+ value: String(field.max ?? 5),
2370
+ onChange: (value) => {
2371
+ const max = Number(value);
2372
+ if (!Number.isInteger(max)) return;
2373
+ updateField(
2374
+ field.id,
2375
+ (current) => current.type === "rating" ? { ...current, min: Math.min(current.min ?? 1, max), max } : current
2376
+ );
2318
2377
  }
2319
- ),
2378
+ }
2379
+ ) })
2380
+ ] }) : null,
2381
+ "options" in field ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__options"), children: [
2382
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: translate("builder.options") }),
2383
+ field.options.map(
2384
+ (option, optionIndex) => OptionEditorSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__option"), children: [
2385
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2386
+ TextInput,
2387
+ {
2388
+ id: `builder-option-${option.id}`,
2389
+ label: translate("builder.optionLabel", { index: optionIndex + 1 }),
2390
+ value: option.label,
2391
+ placeholder: translate("builder.optionLabelPlaceholder"),
2392
+ onChange: (value) => value.trim().length === 0 ? void 0 : updateOption(field.id, option.id, value)
2393
+ }
2394
+ ),
2395
+ ToolbarSlot === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2396
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2397
+ IconButton,
2398
+ {
2399
+ actionType: "moveUp",
2400
+ title: translate("builder.moveUp", { title: option.label }),
2401
+ disabled: optionIndex === 0,
2402
+ onClick: () => moveOption(field.id, option.id, optionIndex - 1)
2403
+ }
2404
+ ),
2405
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2406
+ IconButton,
2407
+ {
2408
+ actionType: "moveDown",
2409
+ title: translate("builder.moveDown", { title: option.label }),
2410
+ disabled: optionIndex === field.options.length - 1,
2411
+ onClick: () => moveOption(field.id, option.id, optionIndex + 1)
2412
+ }
2413
+ ),
2414
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2415
+ IconButton,
2416
+ {
2417
+ actionType: "delete",
2418
+ disabled: field.options.length === 1,
2419
+ onClick: () => removeOption(field.id, option.id),
2420
+ title: translate("builder.remove")
2421
+ }
2422
+ )
2423
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2424
+ ToolbarSlot,
2425
+ {
2426
+ schema,
2427
+ translate,
2428
+ kind: "option",
2429
+ targetId: option.id,
2430
+ index: optionIndex,
2431
+ total: field.options.length,
2432
+ title: option.label,
2433
+ onMoveUp: () => moveOption(field.id, option.id, optionIndex - 1),
2434
+ onMoveDown: () => moveOption(field.id, option.id, optionIndex + 1),
2435
+ onRemove: () => removeOption(field.id, option.id),
2436
+ readOnly,
2437
+ actions,
2438
+ components
2439
+ }
2440
+ )
2441
+ ] }, option.id) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2442
+ OptionEditorSlot,
2443
+ {
2444
+ schema,
2445
+ field,
2446
+ option,
2447
+ index: optionIndex,
2448
+ currentLocale: editingLocale,
2449
+ translate,
2450
+ readOnly,
2451
+ actions,
2452
+ components
2453
+ },
2454
+ option.id
2455
+ )
2456
+ ),
2457
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2458
+ Button,
2459
+ {
2460
+ action: "addOption",
2461
+ targetId: field.id,
2462
+ disabled: policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
2463
+ onClick: () => addOption(field.id),
2464
+ children: translate("builder.addOption")
2465
+ }
2466
+ )
2467
+ ] }) : null,
2468
+ conditionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__condition"), children: [
2469
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2470
+ Select,
2471
+ {
2472
+ id: `builder-field-${field.id}-condition`,
2473
+ label: translate("builder.displayCondition"),
2474
+ value: condition?.questionId ?? "",
2475
+ onChange: (value) => {
2476
+ const selected = schema.fields.find((item) => item.id === value);
2477
+ setDisplayCondition(
2478
+ field.id,
2479
+ selected === void 0 ? void 0 : conditionWithValue(
2480
+ selected.id,
2481
+ conditionOperators(selected)[0] ?? "not_empty",
2482
+ defaultConditionValue(selected)
2483
+ )
2484
+ );
2485
+ },
2486
+ options: [
2487
+ { value: "", label: translate("builder.alwaysVisible") },
2488
+ ...availableSources.map((candidate) => ({
2489
+ value: candidate.id,
2490
+ label: candidate.title
2491
+ }))
2492
+ ]
2493
+ }
2494
+ ) }),
2495
+ condition !== void 0 && source !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2320
2496
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2321
- IconButton,
2497
+ Select,
2322
2498
  {
2323
- actionType: "moveDown",
2324
- title: translate("builder.moveDown", { title: option.label }),
2325
- disabled: optionIndex === field.options.length - 1,
2326
- onClick: () => moveOption(field.id, option.id, optionIndex + 1)
2499
+ "aria-label": translate("builder.conditionOperator"),
2500
+ value: condition.operator,
2501
+ onChange: (value) => {
2502
+ const operator = value;
2503
+ setDisplayCondition(
2504
+ field.id,
2505
+ conditionWithValue(source.id, operator, defaultConditionValue(source))
2506
+ );
2507
+ },
2508
+ options: conditionOperators(source).map((operator) => ({
2509
+ value: operator,
2510
+ label: translate(operatorKey(operator))
2511
+ }))
2327
2512
  }
2328
2513
  ),
2329
2514
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2330
- IconButton,
2515
+ ConditionValueEditor,
2331
2516
  {
2332
- actionType: "delete",
2333
- disabled: field.options.length === 1,
2334
- onClick: () => removeOption(field.id, option.id),
2335
- title: translate("builder.remove")
2517
+ source,
2518
+ condition,
2519
+ onChange: (next) => setDisplayCondition(field.id, next),
2520
+ translate,
2521
+ components
2336
2522
  }
2337
2523
  )
2338
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2339
- ToolbarSlot,
2340
- {
2341
- schema,
2342
- kind: "option",
2343
- targetId: option.id,
2344
- index: optionIndex,
2345
- total: field.options.length,
2346
- title: option.label,
2347
- onMoveUp: () => moveOption(field.id, option.id, optionIndex - 1),
2348
- onMoveDown: () => moveOption(field.id, option.id, optionIndex + 1),
2349
- onRemove: () => removeOption(field.id, option.id),
2350
- readOnly,
2351
- actions,
2352
- components
2353
- }
2354
- )
2355
- ] }, option.id) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2356
- OptionEditorSlot,
2357
- {
2358
- schema,
2359
- field,
2360
- option,
2361
- index: optionIndex,
2362
- currentLocale: editingLocale,
2363
- readOnly,
2364
- actions,
2365
- components
2366
- },
2367
- option.id
2368
- )
2369
- ),
2370
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2371
- Button,
2372
- {
2373
- action: "addOption",
2374
- targetId: field.id,
2375
- disabled: policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
2376
- onClick: () => addOption(field.id),
2377
- children: translate("builder.addOption")
2378
- }
2379
- )
2380
- ] }) : null,
2381
- conditionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: builderClass("form-engine-builder__condition"), children: [
2382
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: builderClass("form-engine-builder__field"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2383
- Select,
2384
- {
2385
- id: `builder-field-${field.id}-condition`,
2386
- label: translate("builder.displayCondition"),
2387
- value: condition?.questionId ?? "",
2388
- onChange: (value) => {
2389
- const selected = schema.fields.find((item) => item.id === value);
2390
- setDisplayCondition(
2391
- field.id,
2392
- selected === void 0 ? void 0 : conditionWithValue(
2393
- selected.id,
2394
- conditionOperators(selected)[0] ?? "not_empty",
2395
- defaultConditionValue(selected)
2396
- )
2397
- );
2398
- },
2399
- options: [
2400
- { value: "", label: translate("builder.alwaysVisible") },
2401
- ...availableSources.map((candidate) => ({ value: candidate.id, label: candidate.title }))
2402
- ]
2403
- }
2404
- ) }),
2405
- condition !== void 0 && source !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2406
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2407
- Select,
2408
- {
2409
- "aria-label": translate("builder.conditionOperator"),
2410
- value: condition.operator,
2411
- onChange: (value) => {
2412
- const operator = value;
2413
- setDisplayCondition(
2414
- field.id,
2415
- conditionWithValue(source.id, operator, defaultConditionValue(source))
2416
- );
2417
- },
2418
- options: conditionOperators(source).map((operator) => ({
2419
- value: operator,
2420
- label: translate(operatorKey(operator))
2421
- }))
2422
- }
2423
- ),
2424
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2425
- ConditionValueEditor,
2426
- {
2427
- source,
2428
- condition,
2429
- onChange: (next) => setDisplayCondition(field.id, next),
2430
- translate,
2431
- components
2432
- }
2433
- )
2434
- ] }) : null
2435
- ] }) : null
2436
- ] }, field.id);
2437
- }) }),
2438
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2524
+ ] }) : null
2525
+ ] }) : null
2526
+ ]
2527
+ },
2528
+ field.id
2529
+ );
2530
+ }) }) }),
2531
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuilderSectionGroup, { name: "addQuestion", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2439
2532
  Button,
2440
2533
  {
2441
2534
  className: builderClass("form-engine-builder__add"),
@@ -2444,8 +2537,8 @@ function FormBuilder({
2444
2537
  onClick: addField,
2445
2538
  children: translate("builder.addQuestion")
2446
2539
  }
2447
- )
2448
- ] })
2540
+ ) })
2541
+ ] }) })
2449
2542
  }
2450
2543
  )
2451
2544
  }