@form-engine-ts/mui 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
@@ -17,319 +17,1291 @@ var __copyProps = (to, from, except, desc) => {
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
- // src/index.tsx
20
+ // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ DEFAULT_MUI_SECTION_ORDER: () => DEFAULT_MUI_SECTION_ORDER,
24
+ MuiButtonAdapter: () => MuiButtonAdapter,
25
+ MuiCheckboxAdapter: () => MuiCheckboxAdapter,
26
+ MuiErrorMessageAdapter: () => MuiErrorMessageAdapter,
27
+ MuiFieldEditorSlot: () => MuiFieldEditorSlot,
28
+ MuiFieldsetAdapter: () => MuiFieldsetAdapter,
29
+ MuiFormBuilder: () => MuiFormBuilder,
30
+ MuiIconButtonAdapter: () => MuiIconButtonAdapter,
31
+ MuiLocalizationSlot: () => MuiLocalizationSlot,
32
+ MuiOptionEditorSlot: () => MuiOptionEditorSlot,
33
+ MuiSectionAdapter: () => MuiSectionAdapter,
34
+ MuiSelectAdapter: () => MuiSelectAdapter,
35
+ MuiTextAreaAdapter: () => MuiTextAreaAdapter,
36
+ MuiTextInputAdapter: () => MuiTextInputAdapter,
37
+ MuiToolbarSlot: () => MuiToolbarSlot,
23
38
  createMuiBuilderComponents: () => createMuiBuilderComponents,
39
+ createMuiBuilderProps: () => createMuiBuilderProps,
40
+ createMuiBuilderSlots: () => createMuiBuilderSlots,
41
+ createMuiButtonAdapter: () => createMuiButtonAdapter,
42
+ createMuiCheckboxAdapter: () => createMuiCheckboxAdapter,
43
+ createMuiErrorMessageAdapter: () => createMuiErrorMessageAdapter,
44
+ createMuiFieldEditorSlot: () => createMuiFieldEditorSlot,
45
+ createMuiFieldsetAdapter: () => createMuiFieldsetAdapter,
46
+ createMuiIconButtonAdapter: () => createMuiIconButtonAdapter,
47
+ createMuiLocalizationSlot: () => createMuiLocalizationSlot,
48
+ createMuiOptionEditorSlot: () => createMuiOptionEditorSlot,
49
+ createMuiSectionAdapter: () => createMuiSectionAdapter,
50
+ createMuiSelectAdapter: () => createMuiSelectAdapter,
51
+ createMuiTextAreaAdapter: () => createMuiTextAreaAdapter,
52
+ createMuiTextInputAdapter: () => createMuiTextInputAdapter,
53
+ createMuiToolbarSlot: () => createMuiToolbarSlot,
24
54
  muiBuilderComponents: () => muiBuilderComponents,
25
- muiDefaultIconResolver: () => muiDefaultIconResolver
55
+ muiBuilderSlots: () => muiBuilderSlots,
56
+ muiDefaultIconResolver: () => muiDefaultIconResolver,
57
+ resolveMuiAdapterOptions: () => resolveMuiAdapterOptions
26
58
  });
27
59
  module.exports = __toCommonJS(index_exports);
28
- var import_icons_material = require("@mui/icons-material");
60
+
61
+ // src/adapters/Button.tsx
29
62
  var import_material = require("@mui/material");
30
- var import_jsx_runtime = require("react/jsx-runtime");
31
- function MuiButtonAdapter({
32
- id,
33
- className,
34
- disabled,
35
- "aria-label": ariaLabel,
36
- onClick,
37
- children,
38
- title,
39
- variant = "secondary",
40
- action,
41
- targetId
42
- }) {
43
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
44
- import_material.Button,
45
- {
46
- id,
47
- className,
48
- type: "button",
49
- disabled,
50
- "aria-label": ariaLabel,
51
- title,
52
- "data-builder-action": action,
53
- "data-target-id": targetId,
54
- onClick,
55
- color: variant === "danger" ? "error" : "primary",
56
- variant: variant === "primary" ? "contained" : "outlined",
57
- children
58
- }
59
- );
60
- }
61
- function MuiIconButtonAdapter({
62
- id,
63
- className,
64
- disabled,
65
- readOnly,
66
- "aria-label": ariaLabel,
67
- "aria-describedby": ariaDescribedBy,
68
- "aria-labelledby": ariaLabelledBy,
69
- onClick,
70
- icon,
71
- title
72
- }) {
73
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
74
- import_material.IconButton,
75
- {
76
- id,
77
- className,
78
- component: "button",
79
- type: "button",
80
- disabled: disabled || readOnly,
81
- "aria-label": ariaLabel ?? title,
82
- "aria-describedby": ariaDescribedBy,
83
- "aria-labelledby": ariaLabelledBy,
84
- title,
85
- onClick,
86
- sx: { minWidth: 0, padding: 0.5 },
87
- children: icon
88
- }
89
- );
90
- }
91
- function MuiTextInputAdapter({
92
- id,
93
- className,
94
- disabled,
95
- readOnly,
96
- "aria-label": ariaLabel,
97
- "aria-describedby": ariaDescribedBy,
98
- "aria-labelledby": ariaLabelledBy,
99
- name,
100
- label,
101
- required,
102
- error,
103
- helperText,
104
- value,
105
- onChange,
106
- placeholder,
107
- maxLength,
108
- inputMode,
109
- type = "text",
110
- min,
111
- max,
112
- step
113
- }) {
114
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
115
- import_material.TextField,
116
- {
117
- id,
118
- className,
119
- name,
120
- label,
121
- required,
122
- error,
123
- helperText,
124
- value,
125
- disabled,
126
- slotProps: {
127
- htmlInput: { maxLength, min, max, step, inputMode },
128
- input: { readOnly },
129
- formHelperText: { id: ariaDescribedBy }
130
- },
131
- type,
132
- placeholder,
133
- "aria-label": ariaLabel,
134
- "aria-describedby": ariaDescribedBy,
135
- "aria-labelledby": ariaLabelledBy,
136
- fullWidth: true,
137
- variant: "outlined",
138
- onChange: (event) => onChange(event.currentTarget.value)
139
- }
140
- );
141
- }
142
- function MuiTextAreaAdapter({
143
- id,
144
- className,
145
- disabled,
146
- readOnly,
147
- "aria-label": ariaLabel,
148
- "aria-describedby": ariaDescribedBy,
149
- "aria-labelledby": ariaLabelledBy,
150
- name,
151
- label,
152
- required,
153
- error,
154
- helperText,
155
- value,
156
- onChange,
157
- placeholder,
158
- maxLength,
159
- rows
160
- }) {
161
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
162
- import_material.TextField,
163
- {
164
- id,
165
- className,
166
- name,
167
- label,
168
- required,
169
- error,
170
- helperText,
171
- value,
172
- disabled,
173
- slotProps: {
174
- htmlInput: { maxLength },
175
- input: { readOnly },
176
- formHelperText: { id: ariaDescribedBy }
177
- },
178
- multiline: true,
179
- rows,
180
- placeholder,
181
- "aria-label": ariaLabel,
182
- "aria-describedby": ariaDescribedBy,
183
- "aria-labelledby": ariaLabelledBy,
184
- fullWidth: true,
185
- variant: "outlined",
186
- onChange: (event) => onChange(event.currentTarget.value)
187
- }
188
- );
63
+
64
+ // src/types.ts
65
+ var DEFAULT_MUI_SECTION_ORDER = [
66
+ "basicSettings",
67
+ "questions",
68
+ "addQuestion",
69
+ "localization"
70
+ ];
71
+ function resolveMuiAdapterOptions(options = {}) {
72
+ const buttonVariant = options.buttonVariant ?? "contained";
73
+ return {
74
+ size: options.size ?? "medium",
75
+ variant: options.variant ?? "outlined",
76
+ buttonVariant,
77
+ buttonVariants: {
78
+ primary: options.buttonVariants?.primary ?? buttonVariant,
79
+ secondary: options.buttonVariants?.secondary ?? buttonVariant,
80
+ danger: options.buttonVariants?.danger ?? buttonVariant
81
+ },
82
+ fullWidth: options.fullWidth ?? true,
83
+ dense: options.dense ?? false,
84
+ getLocaleLabel: options.getLocaleLabel ?? ((locale) => locale),
85
+ ...options.getActionLabel === void 0 ? {} : { getActionLabel: options.getActionLabel },
86
+ layoutOptions: options.layoutOptions ?? {},
87
+ localizationOptions: {
88
+ collapsible: options.localizationOptions?.collapsible ?? false,
89
+ defaultExpanded: options.localizationOptions?.defaultExpanded ?? false
90
+ },
91
+ muiSlotProps: options.muiSlotProps ?? {}
92
+ };
189
93
  }
190
- function MuiSelectAdapter({
191
- id,
192
- className,
193
- disabled,
194
- readOnly,
195
- "aria-label": ariaLabel,
196
- "aria-describedby": ariaDescribedBy,
197
- "aria-labelledby": ariaLabelledBy,
198
- name,
199
- label,
200
- required,
201
- error,
202
- helperText,
203
- value,
204
- onChange,
205
- options
206
- }) {
207
- const labelId = id === void 0 ? void 0 : `${id}-label`;
208
- const handleChange = (event) => onChange(event.target.value);
209
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.FormControl, { className, fullWidth: true, error, required, disabled, children: [
210
- label === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.InputLabel, { id: labelId, children: label }),
211
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
212
- import_material.Select,
94
+
95
+ // src/adapters/Button.tsx
96
+ var import_jsx_runtime = require("react/jsx-runtime");
97
+ function createMuiButtonAdapter(options) {
98
+ const resolved = resolveMuiAdapterOptions(options);
99
+ return function MuiButton({
100
+ id,
101
+ className,
102
+ disabled,
103
+ readOnly,
104
+ "aria-label": ariaLabel,
105
+ "aria-describedby": ariaDescribedBy,
106
+ "aria-labelledby": ariaLabelledBy,
107
+ onClick,
108
+ children,
109
+ title,
110
+ variant,
111
+ action,
112
+ targetId
113
+ }) {
114
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
115
+ import_material.Button,
213
116
  {
214
117
  id,
215
- labelId,
216
- name,
217
- label,
218
- value,
219
- onChange: handleChange,
220
- readOnly,
118
+ className,
119
+ type: "button",
120
+ size: resolved.size,
121
+ disabled: disabled || readOnly,
221
122
  "aria-label": ariaLabel,
222
123
  "aria-describedby": ariaDescribedBy,
223
124
  "aria-labelledby": ariaLabelledBy,
224
- variant: "outlined",
225
- children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.MenuItem, { value: option.value, disabled: option.disabled, children: option.label }, option.value))
125
+ title,
126
+ "data-builder-action": action,
127
+ "data-target-id": targetId,
128
+ onClick,
129
+ color: variant === "danger" ? "error" : "primary",
130
+ variant: resolved.buttonVariants?.[variant ?? "primary"] ?? resolved.buttonVariant,
131
+ fullWidth: resolved.fullWidth,
132
+ children
226
133
  }
227
- ),
228
- helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.FormHelperText, { id: ariaDescribedBy, children: helperText })
229
- ] });
134
+ );
135
+ };
230
136
  }
231
- function MuiCheckboxAdapter({
232
- id,
233
- className,
234
- disabled,
235
- readOnly,
236
- "aria-label": ariaLabel,
237
- checked,
238
- onChange,
239
- label
240
- }) {
241
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
242
- import_material.FormControlLabel,
243
- {
244
- className,
245
- label,
246
- control: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
247
- import_material.Checkbox,
137
+ var MuiButtonAdapter = createMuiButtonAdapter();
138
+
139
+ // src/adapters/Checkbox.tsx
140
+ var import_material2 = require("@mui/material");
141
+ var import_jsx_runtime2 = require("react/jsx-runtime");
142
+ function createMuiCheckboxAdapter(options) {
143
+ const resolved = resolveMuiAdapterOptions(options);
144
+ return function MuiCheckbox({
145
+ id,
146
+ className,
147
+ disabled,
148
+ readOnly,
149
+ "aria-label": ariaLabel,
150
+ "aria-describedby": ariaDescribedBy,
151
+ "aria-labelledby": ariaLabelledBy,
152
+ name,
153
+ required,
154
+ error,
155
+ helperText,
156
+ checked,
157
+ onChange,
158
+ label
159
+ }) {
160
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_material2.FormControl, { className, error: Boolean(error), required, disabled: disabled || readOnly, children: [
161
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
162
+ import_material2.FormControlLabel,
248
163
  {
249
- id,
250
- checked,
251
- disabled: disabled || readOnly,
252
- inputProps: { "aria-label": ariaLabel },
253
- onChange: (event) => onChange(event.target.checked)
164
+ label,
165
+ control: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
166
+ import_material2.Checkbox,
167
+ {
168
+ id,
169
+ name,
170
+ size: resolved.size,
171
+ checked,
172
+ required,
173
+ disabled: disabled || readOnly,
174
+ inputProps: {
175
+ "aria-label": ariaLabel,
176
+ "aria-describedby": ariaDescribedBy,
177
+ "aria-labelledby": ariaLabelledBy
178
+ },
179
+ onChange: (event) => onChange(event.target.checked)
180
+ }
181
+ )
254
182
  }
255
- )
256
- }
257
- );
183
+ ),
184
+ helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_material2.FormHelperText, { id: ariaDescribedBy, children: helperText })
185
+ ] });
186
+ };
258
187
  }
259
- function MuiSectionAdapter({
260
- id,
261
- className,
262
- title,
263
- description,
264
- headingId,
265
- "aria-label": ariaLabel,
266
- children
267
- }) {
268
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
269
- import_material.Paper,
270
- {
271
- id,
272
- className,
273
- "aria-label": ariaLabel,
274
- "aria-labelledby": title === void 0 ? void 0 : headingId,
275
- sx: { p: 2, mb: 2 },
276
- children: [
277
- title === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { id: headingId, variant: "h6", children: title }),
278
- description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { variant: "body2", children: description }),
279
- children
280
- ]
281
- }
282
- );
188
+ var MuiCheckboxAdapter = createMuiCheckboxAdapter();
189
+
190
+ // src/adapters/ErrorMessage.tsx
191
+ var import_material3 = require("@mui/material");
192
+ var import_jsx_runtime3 = require("react/jsx-runtime");
193
+ function createMuiErrorMessageAdapter(_options) {
194
+ return function MuiErrorMessage({
195
+ id,
196
+ className,
197
+ "aria-label": ariaLabel,
198
+ "aria-describedby": ariaDescribedBy,
199
+ "aria-labelledby": ariaLabelledBy,
200
+ message
201
+ }) {
202
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
203
+ import_material3.Alert,
204
+ {
205
+ id,
206
+ className,
207
+ severity: "error",
208
+ "aria-label": ariaLabel,
209
+ "aria-describedby": ariaDescribedBy,
210
+ "aria-labelledby": ariaLabelledBy,
211
+ sx: { my: 1 },
212
+ children: message
213
+ }
214
+ );
215
+ };
216
+ }
217
+ var MuiErrorMessageAdapter = createMuiErrorMessageAdapter();
218
+
219
+ // src/adapters/Fieldset.tsx
220
+ var import_material4 = require("@mui/material");
221
+ var import_jsx_runtime4 = require("react/jsx-runtime");
222
+ function createMuiFieldsetAdapter(options) {
223
+ const resolved = resolveMuiAdapterOptions(options);
224
+ return function MuiFieldset({ className, legend, disabled, children }) {
225
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
226
+ import_material4.Box,
227
+ {
228
+ component: "fieldset",
229
+ className,
230
+ disabled,
231
+ sx: {
232
+ border: 0,
233
+ m: 0,
234
+ p: 0,
235
+ minWidth: 0,
236
+ display: "grid",
237
+ gap: resolved.dense ? 1 : 2,
238
+ "& > div:not(.MuiStack-root):not(.MuiPaper-root)": {
239
+ display: "grid",
240
+ gap: resolved.dense ? 1 : 2
241
+ }
242
+ },
243
+ children: [
244
+ legend === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_material4.Typography, { component: "legend", variant: "subtitle1", fontWeight: "bold", sx: { mb: 1 }, children: legend }),
245
+ children
246
+ ]
247
+ }
248
+ );
249
+ };
283
250
  }
284
- function MuiFieldsetAdapter({ className, legend, disabled, children }) {
285
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { component: "fieldset", className, disabled, sx: { border: 0, m: 0, p: 0 }, children: [
286
- legend === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { component: "legend", variant: "subtitle1", children: legend }),
251
+ var MuiFieldsetAdapter = createMuiFieldsetAdapter();
252
+
253
+ // src/adapters/IconButton.tsx
254
+ var import_material5 = require("@mui/material");
255
+ var import_jsx_runtime5 = require("react/jsx-runtime");
256
+ var FALLBACK_ACTION_LABELS = {
257
+ moveUp: "Move up",
258
+ moveDown: "Move down",
259
+ delete: "Delete",
260
+ add: "Add",
261
+ edit: "Edit",
262
+ settings: "Settings",
263
+ translate: "Translate",
264
+ close: "Close",
265
+ dragHandle: "Reorder"
266
+ };
267
+ function createMuiIconButtonAdapter(options) {
268
+ const resolved = resolveMuiAdapterOptions(options);
269
+ return function MuiIconButton({
270
+ id,
271
+ className,
272
+ disabled,
273
+ readOnly,
274
+ "aria-label": ariaLabel,
275
+ "aria-describedby": ariaDescribedBy,
276
+ "aria-labelledby": ariaLabelledBy,
277
+ onClick,
278
+ icon,
279
+ actionType,
280
+ title
281
+ }) {
282
+ const actionLabel = actionType === void 0 ? "Action" : resolved.getActionLabel?.(actionType) ?? FALLBACK_ACTION_LABELS[actionType];
283
+ const tooltip = title ?? actionLabel;
284
+ const color = actionType === "delete" ? "error" : actionType === "add" ? "primary" : "default";
285
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_material5.Tooltip, { title: tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
286
+ import_material5.IconButton,
287
+ {
288
+ id,
289
+ className,
290
+ type: "button",
291
+ size: resolved.size,
292
+ color,
293
+ disabled: disabled || readOnly,
294
+ "aria-label": ariaLabel ?? tooltip,
295
+ "aria-describedby": ariaDescribedBy,
296
+ "aria-labelledby": ariaLabelledBy,
297
+ onClick,
298
+ children: icon
299
+ }
300
+ ) }) });
301
+ };
302
+ }
303
+ var MuiIconButtonAdapter = createMuiIconButtonAdapter();
304
+
305
+ // src/adapters/Section.tsx
306
+ var import_material6 = require("@mui/material");
307
+ var import_jsx_runtime6 = require("react/jsx-runtime");
308
+ function createMuiSectionAdapter(options) {
309
+ const resolved = resolveMuiAdapterOptions(options);
310
+ return function MuiSection({
311
+ id,
312
+ className,
313
+ title,
314
+ description,
315
+ headingId,
316
+ "aria-label": ariaLabel,
317
+ onClickCapture,
287
318
  children
288
- ] });
319
+ }) {
320
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
321
+ import_material6.Paper,
322
+ {
323
+ ...resolved.muiSlotProps?.paper,
324
+ id,
325
+ className,
326
+ elevation: 0,
327
+ "aria-label": ariaLabel,
328
+ "aria-labelledby": title === void 0 ? void 0 : headingId,
329
+ onClickCapture,
330
+ sx: resolved.muiSlotProps?.paper?.sx ?? {
331
+ p: resolved.dense ? 1.5 : 2,
332
+ mb: resolved.dense ? 1 : 2,
333
+ border: 1,
334
+ borderColor: "divider",
335
+ borderRadius: 1,
336
+ display: "grid",
337
+ gap: resolved.dense ? 1 : 2,
338
+ "& > div:not(.MuiStack-root):not(.MuiPaper-root)": {
339
+ display: "grid",
340
+ gap: resolved.dense ? 1 : 2
341
+ }
342
+ },
343
+ children: [
344
+ title === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material6.Typography, { id: headingId, variant: "subtitle1", fontWeight: "bold", children: title }),
345
+ description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material6.Typography, { variant: "body2", color: "text.secondary", sx: { mb: resolved.dense ? 0.5 : 1.5 }, children: description }),
346
+ children
347
+ ]
348
+ }
349
+ );
350
+ };
351
+ }
352
+ var MuiSectionAdapter = createMuiSectionAdapter();
353
+
354
+ // src/adapters/Select.tsx
355
+ var import_material7 = require("@mui/material");
356
+ var import_jsx_runtime7 = require("react/jsx-runtime");
357
+ function createMuiSelectAdapter(options) {
358
+ const resolved = resolveMuiAdapterOptions(options);
359
+ return function MuiSelect({
360
+ id,
361
+ className,
362
+ disabled,
363
+ readOnly,
364
+ "aria-label": ariaLabel,
365
+ "aria-describedby": ariaDescribedBy,
366
+ "aria-labelledby": ariaLabelledBy,
367
+ name,
368
+ label,
369
+ required,
370
+ error,
371
+ helperText,
372
+ value,
373
+ onChange,
374
+ options: selectOptions
375
+ }) {
376
+ const labelId = id === void 0 || label === void 0 ? void 0 : `${id}-label`;
377
+ const handleChange = (event) => onChange(event.target.value);
378
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
379
+ import_material7.FormControl,
380
+ {
381
+ className,
382
+ fullWidth: resolved.fullWidth,
383
+ size: resolved.size,
384
+ variant: resolved.variant,
385
+ error: Boolean(error),
386
+ required,
387
+ disabled,
388
+ children: [
389
+ label === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_material7.InputLabel, { id: labelId, children: label }),
390
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
391
+ import_material7.Select,
392
+ {
393
+ id,
394
+ labelId,
395
+ name,
396
+ label,
397
+ value,
398
+ onChange: handleChange,
399
+ required,
400
+ readOnly,
401
+ inputProps: {
402
+ "aria-label": ariaLabel,
403
+ "aria-describedby": ariaDescribedBy,
404
+ "aria-labelledby": ariaLabelledBy
405
+ },
406
+ children: selectOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_material7.MenuItem, { value: option.value, disabled: option.disabled, children: option.label }, option.value))
407
+ }
408
+ ),
409
+ helperText === void 0 || helperText.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_material7.FormHelperText, { id: ariaDescribedBy, children: helperText })
410
+ ]
411
+ }
412
+ );
413
+ };
289
414
  }
290
- function MuiErrorMessageAdapter({ className, message }) {
291
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Alert, { className, severity: "error", children: message });
415
+ var MuiSelectAdapter = createMuiSelectAdapter();
416
+
417
+ // src/adapters/TextArea.tsx
418
+ var import_material8 = require("@mui/material");
419
+ var import_jsx_runtime8 = require("react/jsx-runtime");
420
+ function createMuiTextAreaAdapter(options) {
421
+ const resolved = resolveMuiAdapterOptions(options);
422
+ return function MuiTextArea({
423
+ id,
424
+ className,
425
+ disabled,
426
+ readOnly,
427
+ "aria-label": ariaLabel,
428
+ "aria-describedby": ariaDescribedBy,
429
+ "aria-labelledby": ariaLabelledBy,
430
+ name,
431
+ label,
432
+ required,
433
+ error,
434
+ helperText,
435
+ value,
436
+ onChange,
437
+ placeholder,
438
+ maxLength,
439
+ rows
440
+ }) {
441
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
442
+ import_material8.TextField,
443
+ {
444
+ id,
445
+ className,
446
+ name,
447
+ label,
448
+ required,
449
+ error: Boolean(error),
450
+ helperText,
451
+ value,
452
+ disabled,
453
+ slotProps: {
454
+ htmlInput: {
455
+ maxLength,
456
+ "aria-label": ariaLabel,
457
+ "aria-describedby": ariaDescribedBy,
458
+ "aria-labelledby": ariaLabelledBy
459
+ },
460
+ input: { readOnly },
461
+ formHelperText: { id: ariaDescribedBy }
462
+ },
463
+ multiline: true,
464
+ rows,
465
+ placeholder,
466
+ fullWidth: resolved.fullWidth,
467
+ size: resolved.size,
468
+ variant: resolved.variant,
469
+ onChange: (event) => onChange(event.currentTarget.value)
470
+ }
471
+ );
472
+ };
292
473
  }
474
+ var MuiTextAreaAdapter = createMuiTextAreaAdapter();
475
+
476
+ // src/adapters/TextInput.tsx
477
+ var import_material9 = require("@mui/material");
478
+ var import_jsx_runtime9 = require("react/jsx-runtime");
479
+ function createMuiTextInputAdapter(options) {
480
+ const resolved = resolveMuiAdapterOptions(options);
481
+ return function MuiTextInput({
482
+ id,
483
+ className,
484
+ disabled,
485
+ readOnly,
486
+ "aria-label": ariaLabel,
487
+ "aria-describedby": ariaDescribedBy,
488
+ "aria-labelledby": ariaLabelledBy,
489
+ name,
490
+ label,
491
+ required,
492
+ error,
493
+ helperText,
494
+ value,
495
+ onChange,
496
+ placeholder,
497
+ maxLength,
498
+ inputMode,
499
+ type = "text",
500
+ min,
501
+ max,
502
+ step
503
+ }) {
504
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
505
+ import_material9.TextField,
506
+ {
507
+ id,
508
+ className,
509
+ name,
510
+ label,
511
+ required,
512
+ error: Boolean(error),
513
+ helperText,
514
+ value,
515
+ disabled,
516
+ slotProps: {
517
+ htmlInput: {
518
+ maxLength,
519
+ min,
520
+ max,
521
+ step,
522
+ inputMode,
523
+ "aria-label": ariaLabel,
524
+ "aria-describedby": ariaDescribedBy,
525
+ "aria-labelledby": ariaLabelledBy
526
+ },
527
+ input: { readOnly },
528
+ formHelperText: { id: ariaDescribedBy }
529
+ },
530
+ type,
531
+ placeholder,
532
+ fullWidth: resolved.fullWidth,
533
+ size: resolved.size,
534
+ variant: resolved.variant,
535
+ onChange: (event) => onChange(event.currentTarget.value)
536
+ }
537
+ );
538
+ };
539
+ }
540
+ var MuiTextInputAdapter = createMuiTextInputAdapter();
541
+
542
+ // src/icons.tsx
543
+ var import_icons_material = require("@mui/icons-material");
544
+ var import_jsx_runtime10 = require("react/jsx-runtime");
293
545
  function muiDefaultIconResolver(actionType) {
294
546
  switch (actionType) {
295
547
  case "moveUp":
296
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.ArrowUpward, { fontSize: "small" });
548
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.ArrowUpward, { fontSize: "small" });
297
549
  case "moveDown":
298
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.ArrowDownward, { fontSize: "small" });
550
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.ArrowDownward, { fontSize: "small" });
299
551
  case "delete":
300
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.Delete, { fontSize: "small" });
552
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.Delete, { fontSize: "small" });
301
553
  case "add":
302
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.Add, { fontSize: "small" });
554
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.Add, { fontSize: "small" });
303
555
  case "edit":
304
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.Edit, { fontSize: "small" });
556
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.Edit, { fontSize: "small" });
305
557
  case "settings":
306
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.Settings, { fontSize: "small" });
558
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.Settings, { fontSize: "small" });
307
559
  case "translate":
308
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.Translate, { fontSize: "small" });
560
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.Translate, { fontSize: "small" });
309
561
  case "close":
310
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.Close, { fontSize: "small" });
562
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.Close, { fontSize: "small" });
311
563
  case "dragHandle":
312
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_material.DragHandle, { fontSize: "small" });
564
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.DragHandle, { fontSize: "small" });
565
+ }
566
+ }
567
+
568
+ // src/components.ts
569
+ function isAdapterOptions(value) {
570
+ return "size" in value || "variant" in value || "buttonVariant" in value || "fullWidth" in value || "dense" in value;
571
+ }
572
+ function buildMuiBuilderComponents(options) {
573
+ return {
574
+ Button: createMuiButtonAdapter(options),
575
+ IconButton: createMuiIconButtonAdapter(options),
576
+ TextInput: createMuiTextInputAdapter(options),
577
+ TextArea: createMuiTextAreaAdapter(options),
578
+ Select: createMuiSelectAdapter(options),
579
+ Checkbox: createMuiCheckboxAdapter(options),
580
+ Section: createMuiSectionAdapter(options),
581
+ Fieldset: createMuiFieldsetAdapter(options),
582
+ ErrorMessage: createMuiErrorMessageAdapter(options),
583
+ renderIcon: muiDefaultIconResolver
584
+ };
585
+ }
586
+ var muiBuilderComponents = buildMuiBuilderComponents();
587
+ function createMuiBuilderComponents(optionsOrOverrides = {}, customOverrides) {
588
+ const options = isAdapterOptions(optionsOrOverrides) ? optionsOrOverrides : void 0;
589
+ const overrides = customOverrides ?? (options === void 0 ? optionsOrOverrides : {});
590
+ return { ...buildMuiBuilderComponents(options), ...overrides };
591
+ }
592
+
593
+ // src/slots/FieldEditor.tsx
594
+ var import_material12 = require("@mui/material");
595
+
596
+ // src/slots/OptionEditor.tsx
597
+ var import_material10 = require("@mui/material");
598
+ var import_jsx_runtime11 = require("react/jsx-runtime");
599
+ function createMuiOptionEditorSlot(options) {
600
+ const resolved = resolveMuiAdapterOptions(options);
601
+ return function MuiOptionEditor({
602
+ field,
603
+ option,
604
+ index,
605
+ currentLocale,
606
+ readOnly,
607
+ actions,
608
+ components,
609
+ translate
610
+ }) {
611
+ const { IconButton: IconButton2, TextInput } = components;
612
+ const describedBy = option.label.trim().length === 0 ? `mui-option-${option.id}-error` : void 0;
613
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.Stack, { ...resolved.muiSlotProps?.stack, "data-mui-slot": "option-editor", spacing: resolved.dense ? 0.75 : 1, children: [
614
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, alignItems: { sm: "flex-start" }, children: [
615
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
616
+ TextInput,
617
+ {
618
+ id: `mui-option-${option.id}`,
619
+ label: translate("builder.optionLabel", { index: index + 1 }),
620
+ value: option.label,
621
+ required: true,
622
+ error: option.label.trim().length === 0,
623
+ helperText: option.label.trim().length === 0 ? translate("builder.required") : "",
624
+ "aria-describedby": describedBy,
625
+ disabled: readOnly,
626
+ onChange: (value) => actions.updateOption(field.id, option.id, (current) => ({ ...current, label: value }))
627
+ }
628
+ ),
629
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material10.Stack, { direction: "row", spacing: 0.5, children: [
630
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
631
+ IconButton2,
632
+ {
633
+ actionType: "moveUp",
634
+ title: translate("builder.moveUp", { title: option.label }),
635
+ disabled: readOnly || index === 0,
636
+ onClick: () => actions.moveOption(field.id, option.id, index - 1)
637
+ }
638
+ ),
639
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
640
+ IconButton2,
641
+ {
642
+ actionType: "moveDown",
643
+ title: translate("builder.moveDown", { title: option.label }),
644
+ disabled: readOnly || index === field.options.length - 1,
645
+ onClick: () => actions.moveOption(field.id, option.id, index + 1)
646
+ }
647
+ ),
648
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
649
+ IconButton2,
650
+ {
651
+ actionType: "delete",
652
+ title: translate("builder.delete", { title: option.label }),
653
+ disabled: readOnly || field.options.length <= 1,
654
+ onClick: () => actions.removeOption(field.id, option.id)
655
+ }
656
+ )
657
+ ] })
658
+ ] }),
659
+ currentLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
660
+ TextInput,
661
+ {
662
+ id: `mui-option-${option.id}-${currentLocale}`,
663
+ label: translate("builder.translation", {
664
+ locale: resolved.getLocaleLabel?.(currentLocale) ?? currentLocale
665
+ }),
666
+ value: option.translations?.[currentLocale] ?? "",
667
+ disabled: readOnly,
668
+ onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "option", id: option.id }, "label", value)
669
+ }
670
+ )
671
+ ] });
672
+ };
673
+ }
674
+ var MuiOptionEditorSlot = createMuiOptionEditorSlot();
675
+
676
+ // src/slots/Toolbar.tsx
677
+ var import_material11 = require("@mui/material");
678
+ var import_jsx_runtime12 = require("react/jsx-runtime");
679
+ function createMuiToolbarSlot(options) {
680
+ const resolved = resolveMuiAdapterOptions(options);
681
+ return function MuiToolbar({
682
+ kind,
683
+ index,
684
+ total,
685
+ title,
686
+ onMoveUp,
687
+ onMoveDown,
688
+ onRemove,
689
+ readOnly,
690
+ components,
691
+ translate
692
+ }) {
693
+ const { IconButton: IconButton2 } = components;
694
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
695
+ import_material11.Stack,
696
+ {
697
+ ...resolved.muiSlotProps?.stack,
698
+ "data-mui-slot": "toolbar",
699
+ direction: "row",
700
+ spacing: resolved.dense ? 0.5 : 1,
701
+ alignItems: "center",
702
+ sx: resolved.muiSlotProps?.stack?.sx ?? { mb: resolved.dense ? 1 : 2 },
703
+ children: [
704
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
705
+ IconButton2,
706
+ {
707
+ actionType: "moveUp",
708
+ title: translate("builder.moveUp", { title }),
709
+ disabled: readOnly || index === 0,
710
+ onClick: onMoveUp
711
+ }
712
+ ),
713
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
714
+ IconButton2,
715
+ {
716
+ actionType: "moveDown",
717
+ title: translate("builder.moveDown", { title }),
718
+ disabled: readOnly || index === total - 1,
719
+ onClick: onMoveDown
720
+ }
721
+ ),
722
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
723
+ IconButton2,
724
+ {
725
+ actionType: "delete",
726
+ title: translate("builder.delete", { title }),
727
+ disabled: readOnly || kind !== "page" && total <= 1,
728
+ onClick: onRemove
729
+ }
730
+ )
731
+ ]
732
+ }
733
+ );
734
+ };
735
+ }
736
+ var MuiToolbarSlot = createMuiToolbarSlot();
737
+
738
+ // src/slots/FieldEditor.tsx
739
+ var import_jsx_runtime13 = require("react/jsx-runtime");
740
+ var FIELD_TYPES = [
741
+ "text",
742
+ "textarea",
743
+ "number",
744
+ "rating",
745
+ "select",
746
+ "multi-select",
747
+ "checkbox",
748
+ "radio"
749
+ ];
750
+ function isFieldType(value) {
751
+ return FIELD_TYPES.some((type) => type === value);
752
+ }
753
+ function conditionOperators(field) {
754
+ if (field.type === "multi-select") return ["contains", "not_empty"];
755
+ if (field.type === "text" || field.type === "textarea") {
756
+ return ["equals", "not_equals", "contains", "not_empty"];
313
757
  }
758
+ return ["equals", "not_equals", "not_empty"];
759
+ }
760
+ function isConditionOperator(value) {
761
+ return ["equals", "not_equals", "contains", "not_empty"].some((operator) => operator === value);
762
+ }
763
+ function numericValue(value) {
764
+ if (value.trim().length === 0) return void 0;
765
+ const parsed = Number(value);
766
+ return Number.isFinite(parsed) ? parsed : void 0;
314
767
  }
315
- var muiBuilderComponents = {
316
- Button: MuiButtonAdapter,
317
- IconButton: MuiIconButtonAdapter,
318
- TextInput: MuiTextInputAdapter,
319
- TextArea: MuiTextAreaAdapter,
320
- Select: MuiSelectAdapter,
321
- Checkbox: MuiCheckboxAdapter,
322
- Section: MuiSectionAdapter,
323
- Fieldset: MuiFieldsetAdapter,
324
- ErrorMessage: MuiErrorMessageAdapter,
325
- renderIcon: muiDefaultIconResolver
768
+ function updateBound(field, property, value) {
769
+ if (field.type !== "number" && field.type !== "rating") return field;
770
+ const nextValue = numericValue(value);
771
+ if (nextValue !== void 0) return { ...field, [property]: nextValue };
772
+ const { [property]: _removed, ...remaining } = field;
773
+ return remaining;
774
+ }
775
+ function createMuiFieldEditorSlot(options) {
776
+ const resolved = resolveMuiAdapterOptions(options);
777
+ const Toolbar = createMuiToolbarSlot(options);
778
+ const OptionEditor = createMuiOptionEditorSlot(options);
779
+ return function MuiFieldEditor({
780
+ schema,
781
+ field,
782
+ index,
783
+ currentLocale,
784
+ policy,
785
+ features,
786
+ readOnly,
787
+ actions,
788
+ components,
789
+ translate
790
+ }) {
791
+ const { Button: Button2, Checkbox: Checkbox2, Select: Select2, TextArea, TextInput } = components;
792
+ const allowedTypes = policy?.allowedFieldTypes ?? FIELD_TYPES;
793
+ const pageId = schema.pages?.find((page) => page.questionIds.includes(field.id))?.id ?? "";
794
+ const condition = field.displayCondition;
795
+ const conditionSources = schema.fields.slice(0, index);
796
+ const conditionSource = conditionSources.find((source) => source.id === condition?.questionId);
797
+ const titleErrorId = field.title.trim().length === 0 ? `mui-field-${field.id}-title-error` : void 0;
798
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
799
+ import_material12.Card,
800
+ {
801
+ ...resolved.muiSlotProps?.card,
802
+ "data-mui-slot": "field-editor",
803
+ variant: "outlined",
804
+ sx: resolved.muiSlotProps?.card?.sx ?? { mb: resolved.dense ? 1 : 2, p: resolved.dense ? 1.5 : 2 },
805
+ children: [
806
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
807
+ Toolbar,
808
+ {
809
+ schema,
810
+ translate,
811
+ kind: "field",
812
+ targetId: field.id,
813
+ index,
814
+ total: schema.fields.length,
815
+ title: field.title,
816
+ onMoveUp: () => actions.moveField(field.id, index - 1),
817
+ onMoveDown: () => actions.moveField(field.id, index + 1),
818
+ onRemove: () => actions.removeField(field.id),
819
+ readOnly,
820
+ actions,
821
+ components
822
+ }
823
+ ),
824
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { ...resolved.muiSlotProps?.stack, spacing: resolved.dense ? 1 : 2, children: [
825
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material12.Typography, { variant: "subtitle1", fontWeight: "bold", children: field.title }),
826
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
827
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
828
+ TextInput,
829
+ {
830
+ id: `mui-field-${field.id}-title`,
831
+ name: `fields.${field.id}.title`,
832
+ label: translate("builder.questionTitle"),
833
+ value: field.title,
834
+ required: true,
835
+ error: field.title.trim().length === 0,
836
+ helperText: field.title.trim().length === 0 ? translate("builder.required") : "",
837
+ "aria-describedby": titleErrorId,
838
+ disabled: readOnly,
839
+ onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "title", value)
840
+ }
841
+ ),
842
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
843
+ Select2,
844
+ {
845
+ id: `mui-field-${field.id}-type`,
846
+ name: `fields.${field.id}.type`,
847
+ label: translate("builder.type"),
848
+ value: allowedTypes.includes(field.type) ? field.type : "",
849
+ options: FIELD_TYPES.filter((type) => allowedTypes.includes(type)).map((type) => ({
850
+ value: type,
851
+ label: translate(`builder.fieldType.${type}`)
852
+ })),
853
+ disabled: readOnly,
854
+ onChange: (value) => {
855
+ if (isFieldType(value)) actions.changeFieldType(field.id, value);
856
+ }
857
+ }
858
+ )
859
+ ] }),
860
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
861
+ TextArea,
862
+ {
863
+ id: `mui-field-${field.id}-description`,
864
+ name: `fields.${field.id}.description`,
865
+ label: translate("builder.description"),
866
+ value: field.description ?? "",
867
+ rows: resolved.dense ? 2 : 3,
868
+ disabled: readOnly,
869
+ onChange: (value) => actions.setSourceText({ kind: "field", id: field.id }, "description", value)
870
+ }
871
+ ),
872
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
873
+ Checkbox2,
874
+ {
875
+ id: `mui-field-${field.id}-required`,
876
+ name: `fields.${field.id}.required`,
877
+ label: translate("builder.required"),
878
+ checked: field.required,
879
+ disabled: readOnly,
880
+ onChange: (checked) => actions.updateField(field.id, (current) => ({ ...current, required: checked }))
881
+ }
882
+ ),
883
+ features?.pages === false || schema.pages === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
884
+ Select2,
885
+ {
886
+ id: `mui-field-${field.id}-page`,
887
+ label: translate("builder.questionPage"),
888
+ value: pageId,
889
+ options: [
890
+ { value: "", label: translate("builder.unassigned") },
891
+ ...schema.pages.map((page) => ({ value: page.id, label: page.title ?? page.id }))
892
+ ],
893
+ disabled: readOnly,
894
+ onChange: (value) => actions.assignFieldToPage(field.id, value.length === 0 ? null : value)
895
+ }
896
+ ),
897
+ field.type === "number" || field.type === "rating" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
898
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
899
+ TextInput,
900
+ {
901
+ id: `mui-field-${field.id}-minimum`,
902
+ label: translate("builder.minimum"),
903
+ type: "number",
904
+ value: field.min === void 0 ? "" : String(field.min),
905
+ disabled: readOnly,
906
+ onChange: (value) => actions.updateField(field.id, (current) => updateBound(current, "min", value))
907
+ }
908
+ ),
909
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
910
+ TextInput,
911
+ {
912
+ id: `mui-field-${field.id}-maximum`,
913
+ label: translate("builder.maximum"),
914
+ type: "number",
915
+ value: field.max === void 0 ? "" : String(field.max),
916
+ disabled: readOnly,
917
+ onChange: (value) => actions.updateField(field.id, (current) => updateBound(current, "max", value))
918
+ }
919
+ )
920
+ ] }) : null,
921
+ features?.conditions === false || conditionSources.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { direction: { xs: "column", md: "row" }, spacing: resolved.dense ? 1 : 2, children: [
922
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
923
+ Select2,
924
+ {
925
+ id: `mui-field-${field.id}-condition-source`,
926
+ label: translate("builder.displayCondition"),
927
+ value: condition?.questionId ?? "",
928
+ options: [
929
+ { value: "", label: translate("builder.alwaysVisible") },
930
+ ...conditionSources.map((source) => ({ value: source.id, label: source.title }))
931
+ ],
932
+ disabled: readOnly,
933
+ onChange: (value) => actions.setDisplayCondition(
934
+ field.id,
935
+ value.length === 0 ? void 0 : { questionId: value, operator: "equals", value: "" }
936
+ )
937
+ }
938
+ ),
939
+ condition === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
940
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
941
+ Select2,
942
+ {
943
+ id: `mui-field-${field.id}-condition-operator`,
944
+ label: translate("builder.conditionOperator"),
945
+ value: condition.operator,
946
+ options: (conditionSource === void 0 ? [] : conditionOperators(conditionSource)).map(
947
+ (operator) => ({ value: operator, label: translate(`builder.operator.${operator}`) })
948
+ ),
949
+ disabled: readOnly,
950
+ onChange: (value) => {
951
+ if (!isConditionOperator(value)) return;
952
+ actions.setDisplayCondition(
953
+ field.id,
954
+ value === "not_empty" ? { questionId: condition.questionId, operator: value } : { ...condition, operator: value, value: condition.value ?? "" }
955
+ );
956
+ }
957
+ }
958
+ ),
959
+ condition.operator === "not_empty" ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
960
+ TextInput,
961
+ {
962
+ id: `mui-field-${field.id}-condition-value`,
963
+ label: translate("builder.conditionValue"),
964
+ value: condition.value === void 0 ? "" : String(condition.value),
965
+ disabled: readOnly,
966
+ onChange: (value) => actions.setDisplayCondition(field.id, { ...condition, value })
967
+ }
968
+ )
969
+ ] })
970
+ ] }),
971
+ currentLocale.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { spacing: resolved.dense ? 1 : 2, children: [
972
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material12.Typography, { variant: "subtitle2", children: translate("builder.translation", {
973
+ locale: resolved.getLocaleLabel?.(currentLocale) ?? currentLocale
974
+ }) }),
975
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
976
+ TextInput,
977
+ {
978
+ id: `mui-field-${field.id}-${currentLocale}-title`,
979
+ label: translate("builder.translatedQuestionTitle"),
980
+ value: field.translations?.[currentLocale]?.title ?? "",
981
+ disabled: readOnly,
982
+ onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "field", id: field.id }, "title", value)
983
+ }
984
+ ),
985
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
986
+ TextArea,
987
+ {
988
+ id: `mui-field-${field.id}-${currentLocale}-description`,
989
+ label: translate("builder.translatedDescription"),
990
+ value: field.translations?.[currentLocale]?.description ?? "",
991
+ disabled: readOnly,
992
+ onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "field", id: field.id }, "description", value)
993
+ }
994
+ )
995
+ ] }),
996
+ "options" in field ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material12.Stack, { "data-mui-slot": "options", spacing: resolved.dense ? 1 : 2, children: [
997
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material12.Typography, { variant: "subtitle2", children: translate("builder.options") }),
998
+ field.options.map((option, optionIndex) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
999
+ OptionEditor,
1000
+ {
1001
+ schema,
1002
+ field,
1003
+ option,
1004
+ index: optionIndex,
1005
+ currentLocale,
1006
+ translate,
1007
+ readOnly,
1008
+ actions,
1009
+ components
1010
+ },
1011
+ option.id
1012
+ )),
1013
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1014
+ Button2,
1015
+ {
1016
+ action: "addOption",
1017
+ targetId: field.id,
1018
+ disabled: readOnly || policy?.maxOptionsPerField !== void 0 && field.options.length >= policy.maxOptionsPerField,
1019
+ onClick: () => actions.addOption(field.id),
1020
+ children: translate("builder.addOption")
1021
+ }
1022
+ )
1023
+ ] }) : null
1024
+ ] })
1025
+ ]
1026
+ }
1027
+ );
1028
+ };
1029
+ }
1030
+ var MuiFieldEditorSlot = createMuiFieldEditorSlot();
1031
+
1032
+ // src/slots/Localization.tsx
1033
+ var import_icons_material2 = require("@mui/icons-material");
1034
+ var import_material13 = require("@mui/material");
1035
+ var import_react = require("react");
1036
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1037
+ function createMuiLocalizationSlot(options) {
1038
+ const resolved = resolveMuiAdapterOptions(options);
1039
+ return function MuiLocalization({
1040
+ schema,
1041
+ currentLocale,
1042
+ onCurrentLocaleChange,
1043
+ onAutoTranslate,
1044
+ isTranslating,
1045
+ translationError,
1046
+ policy,
1047
+ translationAdapterAvailable,
1048
+ readOnly,
1049
+ actions,
1050
+ components,
1051
+ translate
1052
+ }) {
1053
+ const { Button: Button2, ErrorMessage, Select: Select2, TextArea, TextInput } = components;
1054
+ const [newLocale, setNewLocale] = (0, import_react.useState)("");
1055
+ const locales = Array.from(
1056
+ new Set((schema.supportedLocales ?? []).filter((locale) => locale !== schema.defaultLocale))
1057
+ );
1058
+ const editingLocaleConfigured = locales.includes(currentLocale);
1059
+ const registeredLocales = /* @__PURE__ */ new Set([
1060
+ ...schema.defaultLocale === void 0 ? [] : [schema.defaultLocale],
1061
+ ...schema.supportedLocales ?? []
1062
+ ]);
1063
+ const availableAllowedLocales = policy?.allowedLocales?.filter((locale) => !registeredLocales.has(locale));
1064
+ const localeLimitReached = policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales;
1065
+ const normalizedLocale = newLocale.trim();
1066
+ const localeAllowed = policy?.allowedLocales === void 0 || policy.allowedLocales.includes(normalizedLocale);
1067
+ const canAddLocale = !readOnly && normalizedLocale.length > 0 && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
1068
+ const handleTabChange = (_event, value) => onCurrentLocaleChange(value);
1069
+ const addLocale = () => {
1070
+ if (!canAddLocale) return;
1071
+ const result = actions.addLocale(normalizedLocale);
1072
+ if (!result.success) return;
1073
+ onCurrentLocaleChange(normalizedLocale);
1074
+ setNewLocale("");
1075
+ };
1076
+ const stackProps = resolved.muiSlotProps?.stack;
1077
+ const collapsible = resolved.localizationOptions?.collapsible ?? false;
1078
+ const content = /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1079
+ !collapsible ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }) : null,
1080
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, direction: { xs: "column", sm: "row" }, spacing: resolved.dense ? 1 : 2, children: [
1081
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1082
+ TextInput,
1083
+ {
1084
+ id: "mui-builder-default-locale",
1085
+ label: translate("builder.defaultLocale"),
1086
+ value: schema.defaultLocale ?? "",
1087
+ disabled: readOnly,
1088
+ onChange: (value) => {
1089
+ const result = actions.setDefaultLocale(value);
1090
+ if (result.success && value === currentLocale) onCurrentLocaleChange("");
1091
+ }
1092
+ }
1093
+ ),
1094
+ availableAllowedLocales === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1095
+ TextInput,
1096
+ {
1097
+ id: "mui-builder-new-locale",
1098
+ label: translate("builder.addLocale"),
1099
+ value: newLocale,
1100
+ disabled: readOnly || localeLimitReached,
1101
+ onChange: setNewLocale
1102
+ }
1103
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1104
+ Select2,
1105
+ {
1106
+ id: "mui-builder-new-locale",
1107
+ label: translate("builder.addLocale"),
1108
+ value: newLocale,
1109
+ options: [
1110
+ { value: "", label: "\u2014" },
1111
+ ...availableAllowedLocales.map((locale) => ({
1112
+ value: locale,
1113
+ label: resolved.getLocaleLabel?.(locale) ?? locale
1114
+ }))
1115
+ ],
1116
+ disabled: readOnly || localeLimitReached || availableAllowedLocales.length === 0,
1117
+ onChange: setNewLocale
1118
+ }
1119
+ ),
1120
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button2, { variant: "primary", action: "addLocale", disabled: !canAddLocale, onClick: addLocale, children: translate("builder.addLocale") })
1121
+ ] }),
1122
+ locales.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1123
+ import_material13.Tabs,
1124
+ {
1125
+ value: editingLocaleConfigured ? currentLocale : false,
1126
+ onChange: handleTabChange,
1127
+ variant: "scrollable",
1128
+ scrollButtons: "auto",
1129
+ "aria-label": translate("builder.translationLocale"),
1130
+ children: locales.map((locale) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1131
+ import_material13.Tab,
1132
+ {
1133
+ value: locale,
1134
+ label: resolved.getLocaleLabel?.(locale) ?? locale,
1135
+ disabled: readOnly && locale !== currentLocale
1136
+ },
1137
+ locale
1138
+ ))
1139
+ }
1140
+ ),
1141
+ !translationAdapterAvailable ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1142
+ Button2,
1143
+ {
1144
+ variant: "secondary",
1145
+ disabled: readOnly || !editingLocaleConfigured || isTranslating,
1146
+ onClick: onAutoTranslate,
1147
+ children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
1148
+ }
1149
+ ),
1150
+ translationError === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ErrorMessage, { message: translationError }),
1151
+ !editingLocaleConfigured ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "body2", color: "text.secondary", children: translate("builder.selectLocale") }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Stack, { ...stackProps, spacing: resolved.dense ? 1 : 2, children: [
1152
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1153
+ TextInput,
1154
+ {
1155
+ id: `mui-builder-${currentLocale}-form-title`,
1156
+ label: translate("builder.translatedFormTitle"),
1157
+ value: schema.translations?.[currentLocale]?.title ?? "",
1158
+ disabled: readOnly,
1159
+ onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "title", value)
1160
+ }
1161
+ ),
1162
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1163
+ TextArea,
1164
+ {
1165
+ id: `mui-builder-${currentLocale}-form-description`,
1166
+ label: translate("builder.translatedFormDescription"),
1167
+ value: schema.translations?.[currentLocale]?.description ?? "",
1168
+ disabled: readOnly,
1169
+ onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "description", value)
1170
+ }
1171
+ ),
1172
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1173
+ TextInput,
1174
+ {
1175
+ id: `mui-builder-${currentLocale}-completion-message`,
1176
+ label: translate("builder.translatedCompletionMessage"),
1177
+ value: schema.translations?.[currentLocale]?.completionMessage ?? "",
1178
+ disabled: readOnly,
1179
+ onChange: (value) => actions.setLocaleTranslation(currentLocale, { kind: "form" }, "completionMessage", value)
1180
+ }
1181
+ )
1182
+ ] })
1183
+ ] });
1184
+ const configured = locales.length > 0;
1185
+ const defaultExpanded = resolved.localizationOptions?.defaultExpanded === "when-configured" ? configured : resolved.localizationOptions?.defaultExpanded ?? false;
1186
+ if (collapsible) {
1187
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material13.Accordion, { ...resolved.muiSlotProps?.accordion, "data-mui-slot": "localization", defaultExpanded, children: [
1188
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.AccordionSummary, { expandIcon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_material2.ExpandMore, {}), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.Typography, { variant: "subtitle1", fontWeight: "bold", children: translate("builder.localization") }) }),
1189
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material13.AccordionDetails, { children: content })
1190
+ ] });
1191
+ }
1192
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1193
+ import_material13.Box,
1194
+ {
1195
+ "data-mui-slot": "localization",
1196
+ sx: {
1197
+ mt: resolved.dense ? 1 : 2,
1198
+ p: resolved.dense ? 1.5 : 2,
1199
+ border: 1,
1200
+ borderColor: "divider",
1201
+ borderRadius: 1
1202
+ },
1203
+ children: content
1204
+ }
1205
+ );
1206
+ };
1207
+ }
1208
+ var MuiLocalizationSlot = createMuiLocalizationSlot();
1209
+
1210
+ // src/slots/index.ts
1211
+ var muiBuilderSlots = {
1212
+ sectionOrder: DEFAULT_MUI_SECTION_ORDER,
1213
+ toolbar: createMuiToolbarSlot(),
1214
+ fieldEditor: createMuiFieldEditorSlot(),
1215
+ optionEditor: createMuiOptionEditorSlot(),
1216
+ localization: createMuiLocalizationSlot()
326
1217
  };
327
- function createMuiBuilderComponents(customOverrides = {}) {
328
- return { ...muiBuilderComponents, ...customOverrides };
1218
+ function createMuiBuilderSlots(options, customOverrides = {}) {
1219
+ return {
1220
+ sectionOrder: options?.layoutOptions?.sectionOrder ?? DEFAULT_MUI_SECTION_ORDER,
1221
+ toolbar: createMuiToolbarSlot(options),
1222
+ fieldEditor: createMuiFieldEditorSlot(options),
1223
+ optionEditor: createMuiOptionEditorSlot(options),
1224
+ localization: createMuiLocalizationSlot(options),
1225
+ ...customOverrides
1226
+ };
1227
+ }
1228
+
1229
+ // src/builderProps.ts
1230
+ function createMuiBuilderProps(options, overrides = {}) {
1231
+ return {
1232
+ disableDefaultStyles: true,
1233
+ components: createMuiBuilderComponents(options, overrides.components),
1234
+ slots: createMuiBuilderSlots(options, overrides.slots)
1235
+ };
1236
+ }
1237
+
1238
+ // src/MuiFormBuilder.tsx
1239
+ var import_react2 = require("@form-engine-ts/react");
1240
+ var import_react3 = require("react");
1241
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1242
+ function MuiFormBuilder({
1243
+ muiOptions,
1244
+ layoutOptions,
1245
+ localizationOptions,
1246
+ muiSlotProps,
1247
+ components: customComponents,
1248
+ slots: customSlots,
1249
+ ...props
1250
+ }) {
1251
+ const resolvedMuiOptions = (0, import_react3.useMemo)(
1252
+ () => ({
1253
+ ...muiOptions,
1254
+ ...layoutOptions === void 0 ? {} : { layoutOptions },
1255
+ ...localizationOptions === void 0 ? {} : { localizationOptions },
1256
+ ...muiSlotProps === void 0 ? {} : { muiSlotProps }
1257
+ }),
1258
+ [layoutOptions, localizationOptions, muiOptions, muiSlotProps]
1259
+ );
1260
+ const components = (0, import_react3.useMemo)(
1261
+ () => createMuiBuilderComponents(resolvedMuiOptions, customComponents),
1262
+ [resolvedMuiOptions, customComponents]
1263
+ );
1264
+ const slots = (0, import_react3.useMemo)(
1265
+ () => createMuiBuilderSlots(resolvedMuiOptions, customSlots),
1266
+ [resolvedMuiOptions, customSlots]
1267
+ );
1268
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react2.FormBuilder, { ...props, components, disableDefaultStyles: true, slots });
329
1269
  }
330
1270
  // Annotate the CommonJS export names for ESM import in node:
331
1271
  0 && (module.exports = {
1272
+ DEFAULT_MUI_SECTION_ORDER,
1273
+ MuiButtonAdapter,
1274
+ MuiCheckboxAdapter,
1275
+ MuiErrorMessageAdapter,
1276
+ MuiFieldEditorSlot,
1277
+ MuiFieldsetAdapter,
1278
+ MuiFormBuilder,
1279
+ MuiIconButtonAdapter,
1280
+ MuiLocalizationSlot,
1281
+ MuiOptionEditorSlot,
1282
+ MuiSectionAdapter,
1283
+ MuiSelectAdapter,
1284
+ MuiTextAreaAdapter,
1285
+ MuiTextInputAdapter,
1286
+ MuiToolbarSlot,
332
1287
  createMuiBuilderComponents,
1288
+ createMuiBuilderProps,
1289
+ createMuiBuilderSlots,
1290
+ createMuiButtonAdapter,
1291
+ createMuiCheckboxAdapter,
1292
+ createMuiErrorMessageAdapter,
1293
+ createMuiFieldEditorSlot,
1294
+ createMuiFieldsetAdapter,
1295
+ createMuiIconButtonAdapter,
1296
+ createMuiLocalizationSlot,
1297
+ createMuiOptionEditorSlot,
1298
+ createMuiSectionAdapter,
1299
+ createMuiSelectAdapter,
1300
+ createMuiTextAreaAdapter,
1301
+ createMuiTextInputAdapter,
1302
+ createMuiToolbarSlot,
333
1303
  muiBuilderComponents,
334
- muiDefaultIconResolver
1304
+ muiBuilderSlots,
1305
+ muiDefaultIconResolver,
1306
+ resolveMuiAdapterOptions
335
1307
  });