@aatulwork/customform-renderer 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1796 @@
1
+ import { useMemo, useState, useEffect, useRef, useCallback } from 'react';
2
+ import { Controller, useForm } from 'react-hook-form';
3
+ import { FormControl, FormLabel, TextField as TextField$1, InputLabel, Select, MenuItem, Box, Chip, CircularProgress, OutlinedInput, FormHelperText, FormControlLabel, Checkbox, RadioGroup, Radio, Typography, Switch, Input, useTheme, alpha, useMediaQuery, Tooltip, IconButton, Accordion, AccordionSummary, AccordionDetails, Alert, Stepper, Step, StepLabel, Button, Stack } from '@mui/material';
4
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
5
+ import DoubleArrowOutlinedIcon from '@mui/icons-material/DoubleArrowOutlined';
6
+ import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
7
+ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
8
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
+ import { CKEditor } from '@ckeditor/ckeditor5-react';
10
+ import dayjs2 from 'dayjs';
11
+ import CloseIcon from '@mui/icons-material/Close';
12
+ import CloudUploadIcon from '@mui/icons-material/CloudUpload';
13
+ import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
14
+ import { DatePicker } from '@mui/x-date-pickers/DatePicker';
15
+ import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
16
+ import { TimePicker } from '@mui/x-date-pickers/TimePicker';
17
+ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
18
+ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
19
+
20
+ // src/components/FormRenderer.tsx
21
+
22
+ // src/utils/formHelpers.ts
23
+ var getAllFields = (formSchema) => {
24
+ return formSchema.sections ? formSchema.sections.flatMap((section) => section.fields) : formSchema.fields || [];
25
+ };
26
+ var normalizeInitialValues = (values, formSchema) => {
27
+ if (!values) return values;
28
+ const normalized = { ...values };
29
+ const allFields = getAllFields(formSchema);
30
+ allFields.forEach((field) => {
31
+ const fieldValue = normalized[field.name];
32
+ if (field.type === "select" || field.type === "formReference" || field.type === "apiReference") {
33
+ if (field.allowMultiple) {
34
+ if (fieldValue !== null && fieldValue !== void 0 && fieldValue !== "") {
35
+ if (!Array.isArray(fieldValue)) {
36
+ normalized[field.name] = [fieldValue];
37
+ }
38
+ } else {
39
+ normalized[field.name] = [];
40
+ }
41
+ } else {
42
+ if (Array.isArray(fieldValue) && fieldValue.length > 0) {
43
+ normalized[field.name] = fieldValue[0];
44
+ } else if (Array.isArray(fieldValue) && fieldValue.length === 0) {
45
+ normalized[field.name] = "";
46
+ }
47
+ }
48
+ }
49
+ if (field.type === "file") {
50
+ if (field.allowMultiple) {
51
+ if (fieldValue !== null && fieldValue !== void 0) {
52
+ if (!Array.isArray(fieldValue)) {
53
+ normalized[field.name] = [fieldValue];
54
+ }
55
+ } else {
56
+ normalized[field.name] = [];
57
+ }
58
+ } else {
59
+ if (Array.isArray(fieldValue) && fieldValue.length > 0) {
60
+ normalized[field.name] = fieldValue[0];
61
+ } else if (Array.isArray(fieldValue) && fieldValue.length === 0) {
62
+ normalized[field.name] = null;
63
+ }
64
+ }
65
+ }
66
+ });
67
+ return normalized;
68
+ };
69
+ var getDefaultValue = (field) => {
70
+ switch (field.type) {
71
+ case "checkbox":
72
+ case "toggle":
73
+ return false;
74
+ case "datepicker":
75
+ return null;
76
+ case "file":
77
+ return field.allowMultiple ? [] : null;
78
+ case "select":
79
+ case "formReference":
80
+ case "apiReference":
81
+ return field.allowMultiple ? [] : "";
82
+ case "text":
83
+ case "email":
84
+ case "number":
85
+ case "radio":
86
+ case "ckeditor":
87
+ default:
88
+ return "";
89
+ }
90
+ };
91
+ var transformFormValues = (data, formSchema) => {
92
+ const allFields = getAllFields(formSchema);
93
+ const fieldTypeMap = /* @__PURE__ */ new Map();
94
+ allFields.forEach((field) => {
95
+ fieldTypeMap.set(field.name, field.type);
96
+ });
97
+ const transformedData = {};
98
+ Object.keys(data).forEach((key) => {
99
+ const fieldType = fieldTypeMap.get(key);
100
+ const value = data[key];
101
+ if (value === null || value === void 0) {
102
+ transformedData[key] = value;
103
+ return;
104
+ }
105
+ switch (fieldType) {
106
+ case "number":
107
+ if (value === "" || value === null || value === void 0) {
108
+ transformedData[key] = null;
109
+ } else {
110
+ const numValue = Number(value);
111
+ transformedData[key] = isNaN(numValue) ? value : numValue;
112
+ }
113
+ break;
114
+ case "checkbox":
115
+ case "toggle":
116
+ transformedData[key] = Boolean(value);
117
+ break;
118
+ case "datepicker":
119
+ case "file":
120
+ default:
121
+ transformedData[key] = value;
122
+ }
123
+ });
124
+ return transformedData;
125
+ };
126
+ var TextField = ({ field, control, defaultValue, rules, errors }) => {
127
+ return /* @__PURE__ */ jsx(
128
+ Controller,
129
+ {
130
+ name: field.name,
131
+ control,
132
+ defaultValue,
133
+ rules,
134
+ render: ({ field: formField }) => /* @__PURE__ */ jsxs(
135
+ FormControl,
136
+ {
137
+ fullWidth: true,
138
+ required: field.required,
139
+ error: !!errors[field.name],
140
+ children: [
141
+ /* @__PURE__ */ jsxs(FormLabel, { children: [
142
+ " ",
143
+ field.label
144
+ ] }),
145
+ /* @__PURE__ */ jsx(
146
+ TextField$1,
147
+ {
148
+ ...formField,
149
+ type: field.type === "number" ? "number" : field.type,
150
+ placeholder: field.placeholder || "Enter value",
151
+ fullWidth: true,
152
+ size: "small",
153
+ required: field.required,
154
+ error: !!errors[field.name],
155
+ helperText: errors[field.name]?.message,
156
+ inputProps: field.type === "number" ? {
157
+ min: field.validation?.min,
158
+ max: field.validation?.max
159
+ } : void 0
160
+ }
161
+ )
162
+ ]
163
+ }
164
+ )
165
+ },
166
+ field.name
167
+ );
168
+ };
169
+
170
+ // src/utils/fieldHelpers.ts
171
+ var formatFileSize = (bytes) => {
172
+ if (bytes === 0) return "0 Bytes";
173
+ const k = 1024;
174
+ const sizes = ["Bytes", "KB", "MB", "GB"];
175
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
176
+ return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
177
+ };
178
+ var validateFile = (file, field) => {
179
+ if (field.validation?.allowedFileTypes && field.validation.allowedFileTypes.length > 0) {
180
+ const fileExtension = file.name.split(".").pop()?.toLowerCase();
181
+ const allowedTypes = field.validation.allowedFileTypes.map((t) => t.toLowerCase().replace(".", ""));
182
+ if (!fileExtension || !allowedTypes.includes(fileExtension)) {
183
+ return `File type not allowed. Allowed types: ${field.validation.allowedFileTypes.join(", ")}`;
184
+ }
185
+ }
186
+ if (field.validation?.maxFileSize) {
187
+ if (file.size > field.validation.maxFileSize) {
188
+ const maxSizeFormatted = formatFileSize(field.validation.maxFileSize);
189
+ return `File size exceeds maximum allowed size of ${maxSizeFormatted}`;
190
+ }
191
+ }
192
+ return true;
193
+ };
194
+ var buildFieldRules = (field) => {
195
+ const rules = {};
196
+ if (field.required) {
197
+ rules.required = `${field.label} is required`;
198
+ }
199
+ if (field.type === "file") {
200
+ rules.validate = (value) => {
201
+ if (field.required) {
202
+ if (field.allowMultiple) {
203
+ const files = Array.isArray(value) ? value : [];
204
+ if (files.length === 0) {
205
+ return `${field.label} is required`;
206
+ }
207
+ const hasValidFiles = files.some(
208
+ (file) => file && typeof file === "object" && ("fileName" in file || "fileUrl" in file)
209
+ );
210
+ if (!hasValidFiles) {
211
+ return `${field.label} is required`;
212
+ }
213
+ } else {
214
+ if (!value || typeof value === "object" && !("fileName" in value || "fileUrl" in value)) {
215
+ return `${field.label} is required`;
216
+ }
217
+ }
218
+ }
219
+ return true;
220
+ };
221
+ }
222
+ if ((field.type === "select" || field.type === "formReference" || field.type === "apiReference") && field.allowMultiple) {
223
+ rules.validate = (value) => {
224
+ const values = value;
225
+ if (!values || values.length === 0) {
226
+ if (field.required) {
227
+ return `${field.label} is required`;
228
+ }
229
+ return true;
230
+ }
231
+ return true;
232
+ };
233
+ }
234
+ return rules;
235
+ };
236
+ var normalizeOptions = (options) => {
237
+ if (!options) return [];
238
+ return options.map((opt) => {
239
+ if (typeof opt === "string") {
240
+ return { label: opt, value: opt };
241
+ }
242
+ return opt;
243
+ });
244
+ };
245
+ var SimpleSelect = ({
246
+ label,
247
+ value,
248
+ onChange,
249
+ options,
250
+ placeholder,
251
+ helperText,
252
+ fullWidth = true,
253
+ size = "small",
254
+ required = false,
255
+ error = false,
256
+ disabled = false,
257
+ multiple = false,
258
+ isLoading = false
259
+ }) => {
260
+ const handleChange = (event) => {
261
+ const val = event.target.value;
262
+ onChange(val);
263
+ };
264
+ return /* @__PURE__ */ jsxs(FormControl, { fullWidth, size, required, error, disabled, children: [
265
+ /* @__PURE__ */ jsx(InputLabel, { children: label }),
266
+ /* @__PURE__ */ jsx(
267
+ Select,
268
+ {
269
+ value: value ?? (multiple ? [] : ""),
270
+ onChange: handleChange,
271
+ input: /* @__PURE__ */ jsx(OutlinedInput, { label }),
272
+ multiple,
273
+ disabled: disabled || isLoading,
274
+ endAdornment: isLoading ? /* @__PURE__ */ jsx(CircularProgress, { size: 20 }) : void 0,
275
+ renderValue: (selected) => {
276
+ if (multiple) {
277
+ const selectedValues = selected;
278
+ if (selectedValues.length === 0) {
279
+ return /* @__PURE__ */ jsx("em", { children: placeholder || "Select..." });
280
+ }
281
+ return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexWrap: "wrap", gap: 0.5 }, children: selectedValues.map((val) => {
282
+ const option2 = options.find((opt) => opt.value === val);
283
+ return /* @__PURE__ */ jsx(
284
+ Chip,
285
+ {
286
+ label: option2?.label || val,
287
+ size: "small"
288
+ },
289
+ val
290
+ );
291
+ }) });
292
+ }
293
+ const option = options.find((opt) => opt.value === selected);
294
+ return option?.label || selected || /* @__PURE__ */ jsx("em", { children: placeholder || "Select..." });
295
+ },
296
+ children: options.map((option) => /* @__PURE__ */ jsx(MenuItem, { value: option.value, children: option.label }, option.value))
297
+ }
298
+ ),
299
+ helperText && /* @__PURE__ */ jsx(FormHelperText, { children: helperText })
300
+ ] });
301
+ };
302
+ var SelectField = ({ field, control, defaultValue, rules, errors, services }) => {
303
+ const isMultiple = field.allowMultiple || false;
304
+ const normalizedOptions = normalizeOptions(field.options);
305
+ const selectOptions = useMemo(() => {
306
+ return normalizedOptions.map((opt) => ({
307
+ value: String(opt.value),
308
+ label: opt.label
309
+ }));
310
+ }, [normalizedOptions]);
311
+ const SelectComponent = services?.SelectComponent || SimpleSelect;
312
+ return /* @__PURE__ */ jsx(
313
+ Controller,
314
+ {
315
+ name: field.name,
316
+ control,
317
+ defaultValue,
318
+ rules,
319
+ render: ({ field: formField }) => {
320
+ return /* @__PURE__ */ jsx(
321
+ SelectComponent,
322
+ {
323
+ label: field.label,
324
+ value: formField.value,
325
+ onChange: (value) => {
326
+ formField.onChange(value);
327
+ },
328
+ options: selectOptions,
329
+ placeholder: field.placeholder || "Select...",
330
+ helperText: errors[field.name]?.message,
331
+ fullWidth: true,
332
+ size: "small",
333
+ required: field.required,
334
+ error: !!errors[field.name],
335
+ disabled: false,
336
+ multiple: isMultiple
337
+ }
338
+ );
339
+ }
340
+ },
341
+ field.name
342
+ );
343
+ };
344
+ var CheckboxField = ({ field, control, defaultValue, rules }) => {
345
+ return /* @__PURE__ */ jsx(
346
+ Controller,
347
+ {
348
+ name: field.name,
349
+ control,
350
+ defaultValue,
351
+ rules,
352
+ render: ({ field: formField }) => /* @__PURE__ */ jsx(
353
+ FormControlLabel,
354
+ {
355
+ control: /* @__PURE__ */ jsx(
356
+ Checkbox,
357
+ {
358
+ ...formField,
359
+ checked: formField.value || false,
360
+ size: "small"
361
+ }
362
+ ),
363
+ label: field.label
364
+ }
365
+ )
366
+ },
367
+ field.name
368
+ );
369
+ };
370
+ var RadioField = ({ field, control, defaultValue, rules, errors }) => {
371
+ const normalizedOptions = normalizeOptions(field.options);
372
+ return /* @__PURE__ */ jsx(
373
+ Controller,
374
+ {
375
+ name: field.name,
376
+ control,
377
+ defaultValue,
378
+ rules,
379
+ render: ({ field: formField }) => /* @__PURE__ */ jsxs(FormControl, { component: "fieldset", required: field.required, error: !!errors[field.name], children: [
380
+ /* @__PURE__ */ jsx(FormLabel, { required: field.required, error: !!errors[field.name], children: field.label }),
381
+ /* @__PURE__ */ jsx(RadioGroup, { ...formField, row: true, children: normalizedOptions.map((option, index) => /* @__PURE__ */ jsx(
382
+ FormControlLabel,
383
+ {
384
+ value: option.value,
385
+ control: /* @__PURE__ */ jsx(Radio, { size: "small" }),
386
+ label: option.label
387
+ },
388
+ index
389
+ )) })
390
+ ] })
391
+ },
392
+ field.name
393
+ );
394
+ };
395
+ var ToggleField = ({ field, control, defaultValue, rules, errors }) => {
396
+ return /* @__PURE__ */ jsx(
397
+ Controller,
398
+ {
399
+ name: field.name,
400
+ control,
401
+ defaultValue,
402
+ rules,
403
+ render: ({ field: formField }) => /* @__PURE__ */ jsx(
404
+ FormControlLabel,
405
+ {
406
+ control: /* @__PURE__ */ jsx(
407
+ Switch,
408
+ {
409
+ ...formField,
410
+ checked: formField.value || false,
411
+ size: "medium"
412
+ }
413
+ ),
414
+ label: /* @__PURE__ */ jsxs(Box, { children: [
415
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", children: [
416
+ field.label,
417
+ " ",
418
+ field.required && "*"
419
+ ] }),
420
+ errors[field.name] && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", sx: { display: "block", mt: 0.5 }, children: errors[field.name]?.message })
421
+ ] })
422
+ }
423
+ )
424
+ },
425
+ field.name
426
+ );
427
+ };
428
+ var ColorField = ({ field, control, defaultValue, rules, errors }) => {
429
+ return /* @__PURE__ */ jsx(
430
+ Controller,
431
+ {
432
+ name: field.name,
433
+ control,
434
+ defaultValue,
435
+ rules,
436
+ render: ({ field: formField }) => /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 2, width: "100%" }, children: [
437
+ /* @__PURE__ */ jsx(
438
+ FormLabel,
439
+ {
440
+ required: field.required,
441
+ error: !!errors[field.name],
442
+ children: field.label
443
+ }
444
+ ),
445
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", flex: 1, maxWidth: 200 }, children: [
446
+ /* @__PURE__ */ jsx(
447
+ Input,
448
+ {
449
+ ...formField,
450
+ type: "color",
451
+ sx: {
452
+ width: "20%",
453
+ height: "40px",
454
+ cursor: "pointer",
455
+ border: errors[field.name] ? "1px solid red" : "1px solid rgba(0, 0, 0, 0.23)",
456
+ borderRadius: "4px",
457
+ padding: "1px"
458
+ },
459
+ inputProps: {
460
+ style: {
461
+ height: "100%",
462
+ cursor: "pointer"
463
+ }
464
+ }
465
+ }
466
+ ),
467
+ errors[field.name] && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", sx: { mt: 0.5 }, children: errors[field.name]?.message })
468
+ ] })
469
+ ] })
470
+ },
471
+ field.name
472
+ );
473
+ };
474
+ var defaultFileUploadService = {
475
+ uploadFiles: async () => {
476
+ throw new Error("File upload service not provided. Please provide a fileUpload service in FormServices.");
477
+ }
478
+ };
479
+ var defaultFormReferenceService = {
480
+ fetchOptions: async () => {
481
+ throw new Error("Form reference service not provided. Please provide a formReference service in FormServices.");
482
+ }
483
+ };
484
+ var defaultApiReferenceService = {
485
+ fetchOptions: async () => {
486
+ throw new Error("API reference service not provided. Please provide an apiReference service in FormServices.");
487
+ }
488
+ };
489
+ var defaultDateFormatterService = {
490
+ format: (value, options) => {
491
+ if (!value) return "\u2014";
492
+ const mode = options?.datePickerMode || "date";
493
+ const date = dayjs2(value);
494
+ if (!date.isValid()) return String(value);
495
+ switch (mode) {
496
+ case "date":
497
+ return date.format("DD/MM/YYYY");
498
+ case "time":
499
+ return date.format("hh:mm A");
500
+ case "datetime":
501
+ return date.format("DD/MM/YYYY hh:mm A");
502
+ default:
503
+ return date.format("DD/MM/YYYY");
504
+ }
505
+ }
506
+ };
507
+
508
+ // src/utils/ckeditorLoader.ts
509
+ var loadCKEditor = (scriptPath = "/lib/ckeditor/ckeditor.js") => {
510
+ return new Promise((resolve, reject) => {
511
+ if (window.ClassicEditor) {
512
+ resolve();
513
+ return;
514
+ }
515
+ const existingScript = document.querySelector(`script[src="${scriptPath}"]`);
516
+ if (existingScript) {
517
+ existingScript.addEventListener("load", () => {
518
+ if (window.ClassicEditor) {
519
+ resolve();
520
+ } else {
521
+ reject(new Error("CKEditor script loaded but ClassicEditor not found on window"));
522
+ }
523
+ });
524
+ existingScript.addEventListener("error", () => {
525
+ reject(new Error("Failed to load CKEditor script"));
526
+ });
527
+ return;
528
+ }
529
+ const script = document.createElement("script");
530
+ script.src = scriptPath;
531
+ script.async = true;
532
+ script.onload = () => {
533
+ const checkInterval = setInterval(() => {
534
+ if (window.ClassicEditor) {
535
+ clearInterval(checkInterval);
536
+ resolve();
537
+ }
538
+ }, 100);
539
+ setTimeout(() => {
540
+ clearInterval(checkInterval);
541
+ if (!window.ClassicEditor) {
542
+ reject(new Error("CKEditor script loaded but ClassicEditor not found on window after 10 seconds"));
543
+ }
544
+ }, 1e4);
545
+ };
546
+ script.onerror = () => {
547
+ reject(new Error(`Failed to load CKEditor from ${scriptPath}`));
548
+ };
549
+ document.head.appendChild(script);
550
+ });
551
+ };
552
+ var isCKEditorAvailable = () => {
553
+ return typeof window !== "undefined" && typeof window.ClassicEditor !== "undefined";
554
+ };
555
+ var waitForCKEditor = (timeout = 1e4) => {
556
+ return new Promise((resolve, reject) => {
557
+ if (isCKEditorAvailable()) {
558
+ resolve();
559
+ return;
560
+ }
561
+ const startTime = Date.now();
562
+ const checkInterval = setInterval(() => {
563
+ if (isCKEditorAvailable()) {
564
+ clearInterval(checkInterval);
565
+ resolve();
566
+ } else if (Date.now() - startTime > timeout) {
567
+ clearInterval(checkInterval);
568
+ reject(new Error("CKEditor not available after timeout"));
569
+ }
570
+ }, 100);
571
+ });
572
+ };
573
+
574
+ // src/hooks/useCKEditor.ts
575
+ var useCKEditor = (options = {}) => {
576
+ const {
577
+ scriptPath = "/lib/ckeditor/ckeditor.js",
578
+ autoLoad = true,
579
+ timeout = 1e4
580
+ } = options;
581
+ const [isReady, setIsReady] = useState(false);
582
+ const [isLoading, setIsLoading] = useState(false);
583
+ const [error, setError] = useState(null);
584
+ const load = async () => {
585
+ if (isCKEditorAvailable()) {
586
+ setIsReady(true);
587
+ setIsLoading(false);
588
+ return;
589
+ }
590
+ setIsLoading(true);
591
+ setError(null);
592
+ try {
593
+ await loadCKEditor(scriptPath);
594
+ setIsReady(true);
595
+ } catch (err) {
596
+ const error2 = err instanceof Error ? err : new Error("Failed to load CKEditor");
597
+ setError(error2);
598
+ setIsReady(false);
599
+ } finally {
600
+ setIsLoading(false);
601
+ }
602
+ };
603
+ useEffect(() => {
604
+ if (isCKEditorAvailable()) {
605
+ setIsReady(true);
606
+ return;
607
+ }
608
+ if (autoLoad) {
609
+ load();
610
+ } else {
611
+ waitForCKEditor(timeout).then(() => setIsReady(true)).catch((err) => setError(err instanceof Error ? err : new Error("CKEditor not available")));
612
+ }
613
+ }, [scriptPath, autoLoad, timeout]);
614
+ return {
615
+ isReady,
616
+ isLoading,
617
+ error,
618
+ load
619
+ };
620
+ };
621
+ var CKEditorField = ({ field, control, defaultValue, rules, errors, setValue, formSchema, services }) => {
622
+ const theme = useTheme();
623
+ const editorContainerRef = useRef(null);
624
+ const fileUploadService = services?.fileUpload || defaultFileUploadService;
625
+ const fileBaseUrl = services?.fileBaseUrl || "";
626
+ const licenseKey = services?.ckEditorLicenseKey || "";
627
+ const ckEditorScriptPath = services?.ckEditorScriptPath || "/lib/ckeditor/ckeditor.js";
628
+ const { isReady: isCKEditorReady, isLoading: isCKEditorLoading, error: ckEditorError } = useCKEditor({
629
+ scriptPath: ckEditorScriptPath,
630
+ autoLoad: true
631
+ });
632
+ const createCustomUploadAdapter = useCallback((loader) => {
633
+ return {
634
+ upload: async () => {
635
+ if (!formSchema?.name) {
636
+ throw new Error("Form schema name is required for image uploads");
637
+ }
638
+ try {
639
+ const file = await loader.file;
640
+ if (!file) {
641
+ throw new Error("No file provided");
642
+ }
643
+ if (!file.type.startsWith("image/")) {
644
+ throw new Error("Only image files are allowed");
645
+ }
646
+ const uploadedFiles = await fileUploadService.uploadFiles(
647
+ formSchema.name,
648
+ field.name,
649
+ [file]
650
+ );
651
+ if (uploadedFiles && uploadedFiles.length > 0 && uploadedFiles[0].fileUrl) {
652
+ const fileUrl = uploadedFiles[0].fileUrl;
653
+ const isFullUrl = fileUrl.startsWith("http://") || fileUrl.startsWith("https://");
654
+ const url = isFullUrl ? fileUrl : fileBaseUrl + fileUrl;
655
+ return {
656
+ default: url
657
+ };
658
+ }
659
+ throw new Error("Upload failed: No file URL returned");
660
+ } catch (error) {
661
+ console.error("Upload error:", error);
662
+ const errorMessage = error.response?.data?.message || error.message || "Upload failed";
663
+ throw new Error(errorMessage);
664
+ }
665
+ },
666
+ abort: () => {
667
+ console.log("Upload aborted");
668
+ }
669
+ };
670
+ }, [formSchema?.name, field.name, fileUploadService, fileBaseUrl]);
671
+ if (isCKEditorLoading) {
672
+ return /* @__PURE__ */ jsxs(Box, { children: [
673
+ /* @__PURE__ */ jsx(FormLabel, { required: field.required, error: !!errors[field.name], children: field.label }),
674
+ /* @__PURE__ */ jsx(Box, { sx: { p: 2, textAlign: "center", color: "text.secondary" }, children: "Loading editor..." })
675
+ ] });
676
+ }
677
+ if (ckEditorError || !isCKEditorReady) {
678
+ return /* @__PURE__ */ jsxs(Box, { children: [
679
+ /* @__PURE__ */ jsx(FormLabel, { required: field.required, error: !!errors[field.name], children: field.label }),
680
+ /* @__PURE__ */ jsx(Box, { sx: { p: 2, border: "1px solid", borderColor: "error.main", borderRadius: 1 }, children: /* @__PURE__ */ jsx(FormHelperText, { error: true, children: ckEditorError?.message || "CKEditor failed to load. Please ensure the CKEditor script is loaded." }) })
681
+ ] });
682
+ }
683
+ return /* @__PURE__ */ jsx(
684
+ Controller,
685
+ {
686
+ name: field.name,
687
+ control,
688
+ defaultValue: defaultValue || "",
689
+ rules,
690
+ render: ({ field: formField }) => /* @__PURE__ */ jsxs(Box, { children: [
691
+ /* @__PURE__ */ jsx(
692
+ FormLabel,
693
+ {
694
+ required: field.required,
695
+ error: !!errors[field.name],
696
+ children: field.label
697
+ }
698
+ ),
699
+ /* @__PURE__ */ jsx(
700
+ Box,
701
+ {
702
+ ref: editorContainerRef,
703
+ sx: {
704
+ "& .ck-editor": {
705
+ borderRadius: "4px",
706
+ "& .ck-toolbar": {
707
+ width: "100%",
708
+ maxWidth: "100%",
709
+ overflow: "visible",
710
+ display: "flex",
711
+ flexWrap: "wrap",
712
+ "& .ck-toolbar__items": {
713
+ display: "flex",
714
+ flexWrap: "wrap !important",
715
+ width: "100%",
716
+ maxWidth: "100%",
717
+ "& > *": {
718
+ flexShrink: 0
719
+ }
720
+ }
721
+ },
722
+ "& .ck-editor__editable": {
723
+ minHeight: "100px"
724
+ },
725
+ "&:hover": {
726
+ borderColor: errors[field.name] ? theme.palette.error.main : theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.87)" : theme.palette.primary.main
727
+ },
728
+ "& .ck-focused": {
729
+ border: errors[field.name] ? `1px solid ${theme.palette.error.main} !important` : `1px solid ${theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.23)" : `${theme.palette.primary.main}`} !important`,
730
+ boxShadow: errors[field.name] ? `0 0 0 1px ${theme.palette.error.main}` : `0 0 0 1px ${alpha(theme.palette.primary.main, 0.5)} !important`
731
+ }
732
+ }
733
+ },
734
+ children: window.ClassicEditor && isCKEditorReady && /* @__PURE__ */ jsx(
735
+ CKEditor,
736
+ {
737
+ editor: window.ClassicEditor,
738
+ config: {
739
+ licenseKey,
740
+ initialData: formField.value || ""
741
+ },
742
+ data: formField.value || "",
743
+ onReady: (editor) => {
744
+ if (formSchema?.name) {
745
+ try {
746
+ const fileRepository = editor.plugins.get("FileRepository");
747
+ if (fileRepository) {
748
+ fileRepository.createUploadAdapter = (loader) => {
749
+ return createCustomUploadAdapter(loader);
750
+ };
751
+ } else {
752
+ console.warn("FileRepository plugin not found");
753
+ }
754
+ } catch (error) {
755
+ console.error("Error setting up upload adapter:", error);
756
+ }
757
+ } else {
758
+ console.warn("Form schema name not available, upload adapter not set");
759
+ }
760
+ if (defaultValue && !formField.value) {
761
+ editor.setData(defaultValue);
762
+ setValue?.(field.name, defaultValue);
763
+ }
764
+ },
765
+ onChange: (_event, editor) => {
766
+ const data = editor.getData();
767
+ formField.onChange(data);
768
+ },
769
+ onBlur: () => {
770
+ formField.onBlur();
771
+ }
772
+ }
773
+ )
774
+ }
775
+ ),
776
+ errors[field.name] && /* @__PURE__ */ jsx(FormHelperText, { error: true, sx: { mt: 0.5, mx: 0 }, children: errors[field.name]?.message })
777
+ ] })
778
+ },
779
+ field.name
780
+ );
781
+ };
782
+ var FileField = ({
783
+ field,
784
+ control,
785
+ defaultValue,
786
+ rules,
787
+ errors,
788
+ formSchema,
789
+ uploadingFiles = {},
790
+ setUploadingFiles,
791
+ setError,
792
+ clearErrors,
793
+ services
794
+ }) => {
795
+ const theme = useTheme();
796
+ const isMobile = useMediaQuery(theme.breakpoints.down("md"));
797
+ const acceptTypes = field.validation?.allowedFileTypes ? field.validation.allowedFileTypes.map((type) => `.${type.replace(".", "")}`).join(",") : void 0;
798
+ const isMultiple = field.allowMultiple || false;
799
+ const fileUploadService = services?.fileUpload || defaultFileUploadService;
800
+ return /* @__PURE__ */ jsx(
801
+ Controller,
802
+ {
803
+ name: field.name,
804
+ control,
805
+ defaultValue,
806
+ rules,
807
+ render: ({ field: formField }) => {
808
+ const isUploading = uploadingFiles[field.name] || false;
809
+ let files = [];
810
+ if (isMultiple) {
811
+ files = Array.isArray(formField.value) ? formField.value : [];
812
+ } else {
813
+ files = formField.value ? [formField.value] : [];
814
+ }
815
+ const hasFiles = files.length > 0;
816
+ return /* @__PURE__ */ jsxs(Box, { children: [
817
+ /* @__PURE__ */ jsx(
818
+ FormLabel,
819
+ {
820
+ required: field.required,
821
+ error: !!errors[field.name],
822
+ children: field.label
823
+ }
824
+ ),
825
+ /* @__PURE__ */ jsxs(
826
+ Box,
827
+ {
828
+ component: "label",
829
+ htmlFor: `file-input-${field.name}`,
830
+ sx: {
831
+ display: "flex",
832
+ flexDirection: "column",
833
+ alignItems: "center",
834
+ justifyContent: "center",
835
+ border: "1px dashed",
836
+ borderColor: errors[field.name] ? "error.main" : isUploading ? "primary.main" : hasFiles ? "primary.main" : "divider",
837
+ p: 1,
838
+ cursor: isUploading ? "wait" : "pointer",
839
+ transition: "all 0.2s ease-in-out",
840
+ backgroundColor: isUploading || hasFiles ? "action.hover" : "background.paper",
841
+ opacity: isUploading ? 0.7 : 1,
842
+ pointerEvents: isUploading ? "none" : "auto",
843
+ "&:hover": {
844
+ borderColor: isUploading ? "primary.main" : "primary.main",
845
+ backgroundColor: "action.hover"
846
+ }
847
+ },
848
+ children: [
849
+ /* @__PURE__ */ jsx(
850
+ "input",
851
+ {
852
+ id: `file-input-${field.name}`,
853
+ type: "file",
854
+ hidden: true,
855
+ multiple: isMultiple,
856
+ accept: acceptTypes,
857
+ onChange: async (e) => {
858
+ const fileList = e.target.files;
859
+ if (!fileList || fileList.length === 0) return;
860
+ const newFiles = Array.from(fileList);
861
+ const isUploading2 = uploadingFiles[field.name] || false;
862
+ if (isUploading2) {
863
+ e.target.value = "";
864
+ return;
865
+ }
866
+ for (const file of newFiles) {
867
+ const validationResult = validateFile(file, field);
868
+ if (validationResult !== true) {
869
+ setError?.(field.name, {
870
+ type: "manual",
871
+ message: validationResult
872
+ });
873
+ e.target.value = "";
874
+ return;
875
+ }
876
+ }
877
+ try {
878
+ setUploadingFiles?.((prev) => ({ ...prev, [field.name]: true }));
879
+ clearErrors?.(field.name);
880
+ if (!formSchema?.name) {
881
+ throw new Error("Form schema name is required for file uploads");
882
+ }
883
+ const uploadedFiles = await fileUploadService.uploadFiles(
884
+ formSchema.name,
885
+ field.name,
886
+ newFiles
887
+ );
888
+ if (isMultiple) {
889
+ const currentValue = formField.value;
890
+ const existingFiles = Array.isArray(currentValue) ? currentValue.filter((item) => item && typeof item === "object" && "fileName" in item) : [];
891
+ const allUploadedFiles = [...existingFiles, ...uploadedFiles];
892
+ formField.onChange(allUploadedFiles);
893
+ } else {
894
+ formField.onChange(uploadedFiles[0] || null);
895
+ }
896
+ } catch (error) {
897
+ console.error(`Failed to upload files for field ${field.name}:`, error);
898
+ const errorMessage = error.response?.data?.message || error.message || "Failed to upload files";
899
+ setError?.(field.name, {
900
+ type: "manual",
901
+ message: `Failed to upload files: ${errorMessage}`
902
+ });
903
+ } finally {
904
+ setUploadingFiles?.((prev) => ({ ...prev, [field.name]: false }));
905
+ e.target.value = "";
906
+ }
907
+ },
908
+ disabled: uploadingFiles[field.name] || false
909
+ }
910
+ ),
911
+ isUploading ? /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", alignItems: "center", gap: 1, py: 3, width: "100%" }, children: [
912
+ /* @__PURE__ */ jsx(CircularProgress, { size: 40 }),
913
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "primary.main", sx: { fontWeight: 500 }, children: "Uploading files..." }),
914
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: "Please wait while files are being uploaded" })
915
+ ] }) : !hasFiles ? /* @__PURE__ */ jsxs(Fragment, { children: [
916
+ /* @__PURE__ */ jsx(CloudUploadIcon, { sx: { fontSize: 40, color: "text.secondary", mb: 1 } }),
917
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "text.secondary", children: [
918
+ "Click to upload or drag and drop",
919
+ isMultiple && " (multiple files allowed)"
920
+ ] }),
921
+ field.validation?.allowedFileTypes && field.validation.allowedFileTypes.length > 0 && /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "text.secondary", sx: { mt: 0.5 }, children: [
922
+ "Allowed: ",
923
+ field.validation.allowedFileTypes.join(", ")
924
+ ] }),
925
+ field.validation?.maxFileSize && /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "text.secondary", sx: { mt: 0.5 }, children: [
926
+ "Max size: ",
927
+ formatFileSize(field.validation.maxFileSize),
928
+ " per file"
929
+ ] })
930
+ ] }) : /* @__PURE__ */ jsxs(Box, { sx: { width: "100%" }, children: [
931
+ isMultiple && /* @__PURE__ */ jsxs(Typography, { variant: "body2", sx: { fontWeight: 500, mb: 1.5 }, children: [
932
+ files.length,
933
+ " file",
934
+ files.length !== 1 ? "s" : "",
935
+ " uploaded"
936
+ ] }),
937
+ files.length === 1 && !isMultiple ? /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 2, width: "100%" }, children: [
938
+ /* @__PURE__ */ jsx(InsertDriveFileIcon, { sx: { fontSize: 40, color: "primary.main" } }),
939
+ /* @__PURE__ */ jsxs(Box, { sx: { flexGrow: 1, minWidth: 0 }, children: [
940
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", maxWidth: isMobile ? "200px" : "300px" }, children: files[0] instanceof File ? files[0].name : files[0].originalName || files[0].fileName }),
941
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: formatFileSize(files[0].size || 0) })
942
+ ] }),
943
+ /* @__PURE__ */ jsx(Tooltip, { title: "Remove file", placement: "bottom", arrow: true, children: /* @__PURE__ */ jsx(
944
+ IconButton,
945
+ {
946
+ size: "small",
947
+ onClick: (e) => {
948
+ e.preventDefault();
949
+ e.stopPropagation();
950
+ formField.onChange(null);
951
+ const fileInput = document.getElementById(`file-input-${field.name}`);
952
+ if (fileInput) {
953
+ fileInput.value = "";
954
+ }
955
+ },
956
+ sx: { color: "error.main" },
957
+ children: /* @__PURE__ */ jsx(CloseIcon, { fontSize: "small" })
958
+ }
959
+ ) })
960
+ ] }) : /* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexDirection: "column", gap: 1, width: "100%" }, children: files.map((file, index) => {
961
+ const fileName = file instanceof File ? file.name : file.originalName || file.fileName;
962
+ return /* @__PURE__ */ jsxs(
963
+ Box,
964
+ {
965
+ sx: {
966
+ display: "flex",
967
+ alignItems: "center",
968
+ gap: 1.5,
969
+ p: 1,
970
+ borderRadius: 1,
971
+ backgroundColor: "background.default",
972
+ border: "1px solid",
973
+ borderColor: "divider"
974
+ },
975
+ children: [
976
+ /* @__PURE__ */ jsx(InsertDriveFileIcon, { sx: { fontSize: 32, color: "primary.main" } }),
977
+ /* @__PURE__ */ jsxs(Box, { sx: { flexGrow: 1, minWidth: 0 }, children: [
978
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis" }, children: fileName }),
979
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: formatFileSize(file.size || 0) })
980
+ ] }),
981
+ /* @__PURE__ */ jsx(Tooltip, { title: "Remove file", placement: "bottom", arrow: true, children: /* @__PURE__ */ jsx(
982
+ IconButton,
983
+ {
984
+ size: "small",
985
+ onClick: (e) => {
986
+ e.preventDefault();
987
+ e.stopPropagation();
988
+ if (isMultiple) {
989
+ const updatedFiles = files.filter((_, i) => i !== index);
990
+ formField.onChange(updatedFiles.length > 0 ? updatedFiles : []);
991
+ } else {
992
+ formField.onChange(null);
993
+ }
994
+ },
995
+ sx: { color: "error.main" },
996
+ children: /* @__PURE__ */ jsx(CloseIcon, { fontSize: "small" })
997
+ }
998
+ ) })
999
+ ]
1000
+ },
1001
+ `${fileName}-${index}`
1002
+ );
1003
+ }) })
1004
+ ] })
1005
+ ]
1006
+ }
1007
+ ),
1008
+ errors[field.name] && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", sx: { mt: 1, display: "block" }, children: errors[field.name]?.message })
1009
+ ] });
1010
+ }
1011
+ },
1012
+ field.name
1013
+ );
1014
+ };
1015
+ var FormReferenceField = ({ field, control, defaultValue, rules, errors, services }) => {
1016
+ const isMultiple = field.allowMultiple || false;
1017
+ const [options, setOptions] = useState([]);
1018
+ const [isLoading, setIsLoading] = useState(false);
1019
+ const formReferenceService = services?.formReference || defaultFormReferenceService;
1020
+ useEffect(() => {
1021
+ if (!field.referenceFormName || !field.referenceFieldName) return;
1022
+ setIsLoading(true);
1023
+ formReferenceService.fetchOptions(field.referenceFormName, field.referenceFieldName).then((opts) => {
1024
+ setOptions(opts);
1025
+ }).catch((error) => {
1026
+ console.error("Failed to fetch form reference options:", error);
1027
+ setOptions([]);
1028
+ }).finally(() => {
1029
+ setIsLoading(false);
1030
+ });
1031
+ }, [field.referenceFormName, field.referenceFieldName, formReferenceService]);
1032
+ const selectOptions = useMemo(() => {
1033
+ return options.map((opt) => ({
1034
+ value: String(opt.value),
1035
+ label: opt.label
1036
+ }));
1037
+ }, [options]);
1038
+ const fieldDefaultValue = defaultValue ?? getDefaultValue(field);
1039
+ const fieldRules = rules ?? buildFieldRules(field);
1040
+ const isDisabled = !field.referenceFormName || !field.referenceFieldName;
1041
+ const SelectComponent = services?.SelectComponent || SimpleSelect;
1042
+ return /* @__PURE__ */ jsx(
1043
+ Controller,
1044
+ {
1045
+ name: field.name,
1046
+ control,
1047
+ defaultValue: fieldDefaultValue,
1048
+ rules: fieldRules,
1049
+ render: ({ field: formField }) => {
1050
+ return /* @__PURE__ */ jsx(
1051
+ SelectComponent,
1052
+ {
1053
+ label: field.label,
1054
+ value: formField.value,
1055
+ onChange: (value) => {
1056
+ formField.onChange(value);
1057
+ },
1058
+ options: selectOptions,
1059
+ placeholder: field.placeholder || "Search and select...",
1060
+ helperText: errors[field.name]?.message,
1061
+ fullWidth: true,
1062
+ size: "small",
1063
+ required: field.required,
1064
+ error: !!errors[field.name],
1065
+ disabled: isDisabled || isLoading,
1066
+ multiple: isMultiple,
1067
+ isLoading
1068
+ }
1069
+ );
1070
+ }
1071
+ },
1072
+ field.name
1073
+ );
1074
+ };
1075
+ var ApiReferenceField = ({ field, control, defaultValue, rules, errors, services }) => {
1076
+ const isMultiple = field.allowMultiple || false;
1077
+ const [options, setOptions] = useState([]);
1078
+ const [isLoading, setIsLoading] = useState(false);
1079
+ const apiReferenceService = services?.apiReference || defaultApiReferenceService;
1080
+ useEffect(() => {
1081
+ if (!field.apiEndpoint || !field.apiLabelField) return;
1082
+ setIsLoading(true);
1083
+ apiReferenceService.fetchOptions(field.apiEndpoint, field.apiLabelField, field.apiValueField || "_id").then((opts) => {
1084
+ setOptions(opts);
1085
+ }).catch((error) => {
1086
+ console.error("Failed to fetch API reference options:", error);
1087
+ setOptions([]);
1088
+ }).finally(() => {
1089
+ setIsLoading(false);
1090
+ });
1091
+ }, [field.apiEndpoint, field.apiLabelField, field.apiValueField, apiReferenceService]);
1092
+ const selectOptions = useMemo(() => {
1093
+ return options.map((opt) => ({
1094
+ value: String(opt.value),
1095
+ label: opt.label
1096
+ }));
1097
+ }, [options]);
1098
+ const fieldDefaultValue = defaultValue ?? getDefaultValue(field);
1099
+ const fieldRules = rules ?? buildFieldRules(field);
1100
+ const isDisabled = !field.apiEndpoint || !field.apiLabelField;
1101
+ const SelectComponent = services?.SelectComponent || SimpleSelect;
1102
+ return /* @__PURE__ */ jsx(
1103
+ Controller,
1104
+ {
1105
+ name: field.name,
1106
+ control,
1107
+ defaultValue: fieldDefaultValue,
1108
+ rules: fieldRules,
1109
+ render: ({ field: formField }) => {
1110
+ return /* @__PURE__ */ jsx(
1111
+ SelectComponent,
1112
+ {
1113
+ label: field.label,
1114
+ value: formField.value,
1115
+ onChange: (value) => {
1116
+ formField.onChange(value);
1117
+ },
1118
+ options: selectOptions,
1119
+ placeholder: field.placeholder || "Search and select...",
1120
+ helperText: errors[field.name]?.message,
1121
+ fullWidth: true,
1122
+ size: "small",
1123
+ required: field.required,
1124
+ error: !!errors[field.name],
1125
+ disabled: isDisabled || isLoading,
1126
+ multiple: isMultiple,
1127
+ isLoading
1128
+ }
1129
+ );
1130
+ }
1131
+ },
1132
+ field.name
1133
+ );
1134
+ };
1135
+ var textFieldSlotProps = (field, errors) => ({
1136
+ fullWidth: true,
1137
+ size: "small",
1138
+ required: field.required,
1139
+ error: !!errors[field.name],
1140
+ helperText: errors[field.name]?.message
1141
+ });
1142
+ function resolveDatePickerMode(field) {
1143
+ if (field.datePickerMode) return field.datePickerMode;
1144
+ return field?.displayTime ? "datetime" : "date";
1145
+ }
1146
+ var DateTimePickerField = ({ field, control, defaultValue, rules, errors }) => {
1147
+ const mode = resolveDatePickerMode(field);
1148
+ return /* @__PURE__ */ jsx(
1149
+ Controller,
1150
+ {
1151
+ name: field.name,
1152
+ control,
1153
+ defaultValue,
1154
+ rules,
1155
+ render: ({ field: formField }) => /* @__PURE__ */ jsxs(Fragment, { children: [
1156
+ /* @__PURE__ */ jsx(
1157
+ FormLabel,
1158
+ {
1159
+ required: field.required,
1160
+ error: !!errors[field.name],
1161
+ children: field.label
1162
+ }
1163
+ ),
1164
+ /* @__PURE__ */ jsxs(LocalizationProvider, { dateAdapter: AdapterDayjs, children: [
1165
+ mode === "date" && /* @__PURE__ */ jsx(
1166
+ DatePicker,
1167
+ {
1168
+ format: "DD-MM-YYYY",
1169
+ value: formField.value ? dayjs2(formField.value) : null,
1170
+ onChange: (date) => formField.onChange(date?.toISOString() ?? null),
1171
+ slotProps: { textField: textFieldSlotProps(field, errors) }
1172
+ }
1173
+ ),
1174
+ mode === "datetime" && /* @__PURE__ */ jsx(
1175
+ DateTimePicker,
1176
+ {
1177
+ format: "DD-MM-YYYY hh:mm A",
1178
+ value: formField.value ? dayjs2(formField.value) : null,
1179
+ onChange: (date) => formField.onChange(date?.toISOString() ?? null),
1180
+ slotProps: { textField: textFieldSlotProps(field, errors) }
1181
+ }
1182
+ ),
1183
+ mode === "time" && /* @__PURE__ */ jsx(
1184
+ TimePicker,
1185
+ {
1186
+ format: "hh:mm A",
1187
+ value: formField.value ? dayjs2(formField.value) : null,
1188
+ onChange: (date) => formField.onChange(date?.toISOString() ?? null),
1189
+ slotProps: { textField: textFieldSlotProps(field, errors) }
1190
+ }
1191
+ )
1192
+ ] })
1193
+ ] })
1194
+ },
1195
+ field.name
1196
+ );
1197
+ };
1198
+ var FieldRenderer = (props) => {
1199
+ const { field, formSchema, uploadingFiles, setUploadingFiles, setError, clearErrors, services } = props;
1200
+ const rules = buildFieldRules(field);
1201
+ const defaultValue = getDefaultValue(field);
1202
+ const commonProps = {
1203
+ field,
1204
+ control: props.control,
1205
+ defaultValue,
1206
+ rules,
1207
+ errors: props.errors,
1208
+ setValue: props.setValue,
1209
+ formSchema,
1210
+ services
1211
+ };
1212
+ switch (field.type) {
1213
+ case "text":
1214
+ case "email":
1215
+ case "number":
1216
+ return /* @__PURE__ */ jsx(TextField, { ...commonProps });
1217
+ case "select":
1218
+ return /* @__PURE__ */ jsx(SelectField, { ...commonProps, services });
1219
+ case "checkbox":
1220
+ return /* @__PURE__ */ jsx(CheckboxField, { ...commonProps });
1221
+ case "radio":
1222
+ return /* @__PURE__ */ jsx(RadioField, { ...commonProps });
1223
+ case "datepicker":
1224
+ return /* @__PURE__ */ jsx(DateTimePickerField, { ...commonProps });
1225
+ case "toggle":
1226
+ return /* @__PURE__ */ jsx(ToggleField, { ...commonProps });
1227
+ case "color":
1228
+ return /* @__PURE__ */ jsx(ColorField, { ...commonProps });
1229
+ case "ckeditor":
1230
+ return /* @__PURE__ */ jsx(CKEditorField, { ...commonProps, formSchema, setValue: props.setValue });
1231
+ case "file":
1232
+ return /* @__PURE__ */ jsx(
1233
+ FileField,
1234
+ {
1235
+ ...commonProps,
1236
+ uploadingFiles,
1237
+ setUploadingFiles,
1238
+ setError,
1239
+ clearErrors
1240
+ }
1241
+ );
1242
+ case "formReference":
1243
+ return /* @__PURE__ */ jsx(FormReferenceField, { ...commonProps, services });
1244
+ case "apiReference":
1245
+ return /* @__PURE__ */ jsx(ApiReferenceField, { ...commonProps, services });
1246
+ default:
1247
+ return null;
1248
+ }
1249
+ };
1250
+ var FieldView = ({ field, value, services }) => {
1251
+ const dateFormatter = services?.dateFormatter || defaultDateFormatterService;
1252
+ const FileDisplayComponent = services?.FileDisplayComponent;
1253
+ const CKEditorDisplayComponent = services?.CKEditorDisplayComponent;
1254
+ const formattedValue = formatFieldValue(field, value, dateFormatter);
1255
+ if (field.type === "file") {
1256
+ if (FileDisplayComponent) {
1257
+ return /* @__PURE__ */ jsxs(
1258
+ Box,
1259
+ {
1260
+ sx: {
1261
+ display: "flex",
1262
+ flexDirection: "column",
1263
+ gap: 0.5,
1264
+ py: 1.5,
1265
+ px: 1,
1266
+ borderColor: "divider"
1267
+ },
1268
+ children: [
1269
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: 500 }, children: field.label }),
1270
+ /* @__PURE__ */ jsx(FileDisplayComponent, { fieldValue: value })
1271
+ ]
1272
+ },
1273
+ field.name
1274
+ );
1275
+ }
1276
+ return /* @__PURE__ */ jsxs(
1277
+ Box,
1278
+ {
1279
+ sx: {
1280
+ display: "flex",
1281
+ flexDirection: "column",
1282
+ gap: 0.5,
1283
+ py: 1.5,
1284
+ px: 1,
1285
+ borderColor: "divider"
1286
+ },
1287
+ children: [
1288
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: 500 }, children: field.label }),
1289
+ /* @__PURE__ */ jsx(Typography, { variant: "body1", sx: { color: "text.secondary" }, children: value ? Array.isArray(value) ? `${value.length} file(s)` : "1 file" : "\u2014" })
1290
+ ]
1291
+ },
1292
+ field.name
1293
+ );
1294
+ }
1295
+ if (field.type === "ckeditor") {
1296
+ if (CKEditorDisplayComponent) {
1297
+ return /* @__PURE__ */ jsxs(
1298
+ Box,
1299
+ {
1300
+ sx: {
1301
+ display: "flex",
1302
+ flexDirection: "column",
1303
+ gap: 0.5,
1304
+ py: 1.5,
1305
+ px: 1,
1306
+ borderColor: "divider"
1307
+ },
1308
+ children: [
1309
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: 500 }, children: field.label }),
1310
+ /* @__PURE__ */ jsx(
1311
+ CKEditorDisplayComponent,
1312
+ {
1313
+ content: value || "",
1314
+ maxLength: 150,
1315
+ showViewButton: true
1316
+ }
1317
+ )
1318
+ ]
1319
+ },
1320
+ field.name
1321
+ );
1322
+ }
1323
+ return /* @__PURE__ */ jsxs(
1324
+ Box,
1325
+ {
1326
+ sx: {
1327
+ display: "flex",
1328
+ flexDirection: "column",
1329
+ gap: 0.5,
1330
+ py: 1.5,
1331
+ px: 1,
1332
+ borderColor: "divider"
1333
+ },
1334
+ children: [
1335
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: 500 }, children: field.label }),
1336
+ /* @__PURE__ */ jsx(
1337
+ Typography,
1338
+ {
1339
+ variant: "body1",
1340
+ sx: {
1341
+ color: formattedValue === "\u2014" ? "text.disabled" : "text.primary",
1342
+ fontStyle: formattedValue === "\u2014" ? "italic" : "normal"
1343
+ },
1344
+ dangerouslySetInnerHTML: { __html: value || "" }
1345
+ }
1346
+ )
1347
+ ]
1348
+ },
1349
+ field.name
1350
+ );
1351
+ }
1352
+ return /* @__PURE__ */ jsxs(
1353
+ Box,
1354
+ {
1355
+ sx: {
1356
+ display: "flex",
1357
+ flexDirection: "column",
1358
+ gap: 0.5,
1359
+ py: 1.5,
1360
+ px: 1,
1361
+ borderColor: "divider"
1362
+ },
1363
+ children: [
1364
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: 500 }, children: field.label }),
1365
+ /* @__PURE__ */ jsx(
1366
+ Typography,
1367
+ {
1368
+ variant: "body1",
1369
+ sx: {
1370
+ color: formattedValue === "\u2014" ? "text.disabled" : "text.primary",
1371
+ fontStyle: formattedValue === "\u2014" ? "italic" : "normal",
1372
+ fontWeight: 400,
1373
+ fontSize: "0.875rem",
1374
+ lineHeight: 1.5
1375
+ },
1376
+ children: formattedValue
1377
+ }
1378
+ )
1379
+ ]
1380
+ },
1381
+ field.name
1382
+ );
1383
+ };
1384
+ var formatFieldValue = (field, value, dateFormatter, services) => {
1385
+ if (value === null || value === void 0 || value === "") {
1386
+ return "\u2014";
1387
+ }
1388
+ switch (field.type) {
1389
+ case "checkbox":
1390
+ case "toggle":
1391
+ return value ? "Yes" : "No";
1392
+ case "datepicker":
1393
+ return dateFormatter?.format(value, { datePickerMode: field.datePickerMode }) || String(value);
1394
+ case "select":
1395
+ case "formReference":
1396
+ case "apiReference":
1397
+ let values;
1398
+ if (field.allowMultiple) {
1399
+ values = Array.isArray(value) ? value : value ? [value] : [];
1400
+ } else {
1401
+ if (Array.isArray(value)) {
1402
+ values = value.length > 0 ? [value[0]] : [];
1403
+ } else {
1404
+ values = value ? [value] : [];
1405
+ }
1406
+ }
1407
+ if (values.length === 0) {
1408
+ return "\u2014";
1409
+ }
1410
+ const getLabelForValue = (val) => {
1411
+ if (field.options) {
1412
+ const normalizedOptions = normalizeOptions(field.options);
1413
+ const option = normalizedOptions.find((opt) => {
1414
+ return opt.value === val || String(opt.value) === String(val);
1415
+ });
1416
+ if (option) {
1417
+ return option.label;
1418
+ }
1419
+ }
1420
+ return String(val);
1421
+ };
1422
+ if (values.length > 1 || field.allowMultiple) {
1423
+ const labels = values.map((val) => getLabelForValue(val));
1424
+ return labels.join(", ");
1425
+ }
1426
+ return getLabelForValue(values[0]);
1427
+ case "radio":
1428
+ if (field.options) {
1429
+ const normalizedOptions = normalizeOptions(field.options);
1430
+ const option = normalizedOptions.find((opt) => {
1431
+ return opt.value === value;
1432
+ });
1433
+ if (option) {
1434
+ return option.label;
1435
+ }
1436
+ }
1437
+ return String(value);
1438
+ default:
1439
+ return String(value);
1440
+ }
1441
+ };
1442
+ var FormViewMode = ({ formSchema, initialValues, hideTitle = false, services }) => {
1443
+ const fieldsToRender = getAllFields(formSchema);
1444
+ const theme = useTheme();
1445
+ const isMobile = useMediaQuery(theme.breakpoints.down("md"));
1446
+ return /* @__PURE__ */ jsxs(Box, { sx: { maxWidth: 600, mx: "auto", width: "100%" }, children: [
1447
+ !hideTitle && /* @__PURE__ */ jsx(Typography, { variant: "h6", gutterBottom: true, sx: { mb: 2, fontWeight: 600 }, children: formSchema.title }),
1448
+ formSchema.sections && formSchema.sections.length > 0 ? /* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexDirection: "column", gap: 1.5 }, children: formSchema.sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs(Accordion, { defaultExpanded: sectionIndex === 0, children: [
1449
+ /* @__PURE__ */ jsx(
1450
+ AccordionSummary,
1451
+ {
1452
+ expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}),
1453
+ "aria-controls": `panel-${section.id}-content`,
1454
+ id: `panel-${section.id}-header`,
1455
+ children: /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
1456
+ /* @__PURE__ */ jsx(DoubleArrowOutlinedIcon, { fontSize: "small", color: "primary" }),
1457
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", sx: { fontWeight: 600 }, color: "primary", children: section.title })
1458
+ ] })
1459
+ }
1460
+ ),
1461
+ /* @__PURE__ */ jsxs(AccordionDetails, { children: [
1462
+ section.description && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1.5, display: "block" }, children: section.description }),
1463
+ /* @__PURE__ */ jsx(
1464
+ Box,
1465
+ {
1466
+ sx: {
1467
+ display: "grid",
1468
+ gridTemplateColumns: isMobile ? "repeat(1, 1fr)" : "repeat(2, 1fr)",
1469
+ gap: 1
1470
+ },
1471
+ children: section.fields.map((field) => /* @__PURE__ */ jsx(FieldView, { field, value: initialValues?.[field.name], services }, field.name))
1472
+ }
1473
+ )
1474
+ ] })
1475
+ ] }, section.id)) }) : /* @__PURE__ */ jsx(
1476
+ Box,
1477
+ {
1478
+ sx: {
1479
+ display: "grid",
1480
+ gridTemplateColumns: "repeat(2, 1fr)",
1481
+ gap: 1
1482
+ },
1483
+ children: fieldsToRender.map((field) => /* @__PURE__ */ jsx(FieldView, { field, value: initialValues?.[field.name], services }, field.name))
1484
+ }
1485
+ )
1486
+ ] });
1487
+ };
1488
+ var FormRenderer = ({
1489
+ formSchema,
1490
+ onSubmit,
1491
+ onCancel,
1492
+ isLoading = false,
1493
+ onSuccess,
1494
+ initialValues,
1495
+ hideTitle = false,
1496
+ allowResetOnValuesChange = false,
1497
+ mode = "edit",
1498
+ services
1499
+ }) => {
1500
+ const {
1501
+ control,
1502
+ handleSubmit,
1503
+ reset,
1504
+ clearErrors,
1505
+ setValue,
1506
+ setError,
1507
+ formState: { errors }
1508
+ } = useForm({
1509
+ defaultValues: initialValues || {}
1510
+ });
1511
+ const [submitError, setSubmitError] = useState(null);
1512
+ const prevInitialValuesRef = useRef(initialValues);
1513
+ const isFormInitializedRef = useRef(false);
1514
+ const [uploadingFiles, setUploadingFiles] = useState({});
1515
+ const [activeStep, setActiveStep] = useState(0);
1516
+ useEffect(() => {
1517
+ setActiveStep(0);
1518
+ }, [formSchema]);
1519
+ useEffect(() => {
1520
+ const wasUndefined = prevInitialValuesRef.current === void 0;
1521
+ const isNowDefined = initialValues !== void 0;
1522
+ if (initialValues) {
1523
+ const normalizedValues = normalizeInitialValues(initialValues, formSchema);
1524
+ if (allowResetOnValuesChange) {
1525
+ const prevValues = prevInitialValuesRef.current;
1526
+ const valuesChanged = !prevValues || JSON.stringify(prevValues) !== JSON.stringify(normalizedValues);
1527
+ if (valuesChanged) {
1528
+ reset(normalizedValues);
1529
+ setSubmitError(null);
1530
+ isFormInitializedRef.current = true;
1531
+ }
1532
+ } else if (wasUndefined && isNowDefined) {
1533
+ reset(normalizedValues);
1534
+ setSubmitError(null);
1535
+ isFormInitializedRef.current = true;
1536
+ }
1537
+ } else if (initialValues === void 0 && prevInitialValuesRef.current !== void 0) {
1538
+ setSubmitError(null);
1539
+ isFormInitializedRef.current = false;
1540
+ }
1541
+ prevInitialValuesRef.current = initialValues;
1542
+ }, [initialValues, reset, allowResetOnValuesChange, formSchema]);
1543
+ const fieldsToRender = useMemo(() => getAllFields(formSchema), [formSchema]);
1544
+ useMemo(() => {
1545
+ return fieldsToRender.filter(
1546
+ (field) => field.type === "formReference" && field.referenceFormName && field.referenceFieldName
1547
+ );
1548
+ }, [fieldsToRender]);
1549
+ useMemo(() => {
1550
+ return fieldsToRender.filter(
1551
+ (field) => field.type === "apiReference" && field.apiEndpoint && field.apiLabelField
1552
+ );
1553
+ }, [fieldsToRender]);
1554
+ const handleFormSubmit = async (data) => {
1555
+ setSubmitError(null);
1556
+ const transformedData = transformFormValues(data, formSchema);
1557
+ if (onSubmit) {
1558
+ try {
1559
+ await onSubmit(transformedData);
1560
+ if (onSuccess) {
1561
+ reset(initialValues || {});
1562
+ onSuccess();
1563
+ }
1564
+ } catch (error) {
1565
+ console.error("Form submission error:", error);
1566
+ let errorMessage = "Form submission failed. Please try again.";
1567
+ if (error?.response?.data) {
1568
+ const errorData = error.response.data;
1569
+ errorMessage = errorData.message || errorData.error || errorData.errors?.message || (Array.isArray(errorData.errors) ? errorData.errors.join(", ") : null) || errorData.msg || errorMessage;
1570
+ } else if (error?.message) {
1571
+ errorMessage = error.message;
1572
+ }
1573
+ setSubmitError(errorMessage);
1574
+ }
1575
+ } else {
1576
+ console.log("Form Data:", transformedData);
1577
+ }
1578
+ };
1579
+ if (mode === "view") {
1580
+ return /* @__PURE__ */ jsx(FormViewMode, { formSchema, initialValues, hideTitle, services });
1581
+ }
1582
+ return /* @__PURE__ */ jsxs(Box, { component: "form", onSubmit: handleSubmit(handleFormSubmit), sx: { mx: "auto", width: "100%" }, children: [
1583
+ !hideTitle && /* @__PURE__ */ jsx(Typography, { variant: "h6", gutterBottom: true, sx: { mb: 2, fontWeight: 600 }, children: formSchema.title }),
1584
+ submitError && /* @__PURE__ */ jsx(Alert, { severity: "error", sx: { mb: 2 }, onClose: () => setSubmitError(null), children: submitError }),
1585
+ formSchema.sections && formSchema.sections.length > 0 ? (() => {
1586
+ const sectionDisplayMode = formSchema.settings?.sectionDisplayMode || "panel";
1587
+ const fieldsPerRow = formSchema.settings?.fieldsPerRow || 1;
1588
+ const gridColumns = Math.min(Math.max(1, fieldsPerRow), 3);
1589
+ const fullWidthFieldTypes = ["ckeditor"];
1590
+ const renderFieldsGrid = (section) => /* @__PURE__ */ jsx(
1591
+ Box,
1592
+ {
1593
+ sx: {
1594
+ display: "grid",
1595
+ gridTemplateColumns: {
1596
+ xs: "1fr",
1597
+ sm: gridColumns === 1 ? "1fr" : gridColumns === 2 ? "repeat(2, 1fr)" : "repeat(3, 1fr)"
1598
+ },
1599
+ gap: "10px"
1600
+ },
1601
+ children: section.fields.map((field) => {
1602
+ const shouldTakeFullWidth = fullWidthFieldTypes.includes(field.type);
1603
+ return /* @__PURE__ */ jsx(
1604
+ Box,
1605
+ {
1606
+ sx: {
1607
+ gridColumn: shouldTakeFullWidth ? {
1608
+ xs: "1 / -1",
1609
+ sm: "1 / -1"
1610
+ } : "auto"
1611
+ },
1612
+ children: /* @__PURE__ */ jsx(
1613
+ FieldRenderer,
1614
+ {
1615
+ field,
1616
+ control,
1617
+ errors,
1618
+ setValue,
1619
+ formSchema,
1620
+ uploadingFiles,
1621
+ setUploadingFiles,
1622
+ setError,
1623
+ clearErrors,
1624
+ services
1625
+ }
1626
+ )
1627
+ },
1628
+ field.name
1629
+ );
1630
+ })
1631
+ }
1632
+ );
1633
+ if (sectionDisplayMode === "stepper") {
1634
+ return /* @__PURE__ */ jsxs(Box, { sx: { border: "1px solid", borderColor: "divider", p: 5, backgroundColor: "background.paper" }, children: [
1635
+ /* @__PURE__ */ jsx(Stepper, { activeStep, orientation: "horizontal", children: formSchema.sections.map((section) => /* @__PURE__ */ jsx(Step, { children: /* @__PURE__ */ jsx(StepLabel, { children: /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", sx: { fontWeight: 600 }, children: section.title }) }) }, section.id)) }),
1636
+ /* @__PURE__ */ jsx(Box, { sx: { mt: 5 }, children: formSchema.sections.map((section, sectionIndex) => {
1637
+ const sectionsLength = formSchema.sections?.length || 0;
1638
+ return /* @__PURE__ */ jsxs(
1639
+ Box,
1640
+ {
1641
+ sx: {
1642
+ display: activeStep === sectionIndex ? "block" : "none"
1643
+ },
1644
+ children: [
1645
+ section.description && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1.5, display: "block" }, children: section.description }),
1646
+ renderFieldsGrid(section),
1647
+ /* @__PURE__ */ jsxs(Box, { sx: { mt: 2, display: "flex", gap: 1, borderTop: "1px solid", pt: 2, borderColor: "divider", justifyContent: "center" }, children: [
1648
+ sectionIndex > 0 && /* @__PURE__ */ jsx(
1649
+ Button,
1650
+ {
1651
+ size: "small",
1652
+ variant: "outlined",
1653
+ color: "success",
1654
+ startIcon: /* @__PURE__ */ jsx(ArrowBackIcon, {}),
1655
+ onClick: () => setActiveStep(sectionIndex - 1),
1656
+ children: "Previous"
1657
+ }
1658
+ ),
1659
+ sectionIndex < sectionsLength - 1 && /* @__PURE__ */ jsx(
1660
+ Button,
1661
+ {
1662
+ variant: "outlined",
1663
+ size: "small",
1664
+ color: "warning",
1665
+ endIcon: /* @__PURE__ */ jsx(ArrowForwardIcon, {}),
1666
+ onClick: () => {
1667
+ if (sectionIndex < sectionsLength - 1) {
1668
+ setActiveStep(sectionIndex + 1);
1669
+ }
1670
+ },
1671
+ children: "Next"
1672
+ }
1673
+ )
1674
+ ] })
1675
+ ]
1676
+ },
1677
+ section.id
1678
+ );
1679
+ }) })
1680
+ ] });
1681
+ }
1682
+ return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexDirection: "column", gap: 1.5 }, children: formSchema.sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs(Accordion, { defaultExpanded: sectionIndex === 0, children: [
1683
+ /* @__PURE__ */ jsx(
1684
+ AccordionSummary,
1685
+ {
1686
+ expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}),
1687
+ "aria-controls": `panel-${section.id}-content`,
1688
+ id: `panel-${section.id}-header`,
1689
+ children: /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
1690
+ /* @__PURE__ */ jsx(DoubleArrowOutlinedIcon, { fontSize: "small", color: "primary" }),
1691
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", color: "primary", sx: { fontWeight: 600 }, children: section.title })
1692
+ ] })
1693
+ }
1694
+ ),
1695
+ /* @__PURE__ */ jsxs(AccordionDetails, { children: [
1696
+ section.description && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1.5, display: "block" }, children: section.description }),
1697
+ renderFieldsGrid(section)
1698
+ ] })
1699
+ ] }, section.id)) });
1700
+ })() : (() => {
1701
+ const fieldsPerRow = formSchema.settings?.fieldsPerRow || 1;
1702
+ const gridColumns = Math.min(Math.max(1, fieldsPerRow), 3);
1703
+ const fullWidthFieldTypes = ["ckeditor"];
1704
+ return /* @__PURE__ */ jsx(
1705
+ Box,
1706
+ {
1707
+ sx: {
1708
+ display: "grid",
1709
+ gridTemplateColumns: {
1710
+ xs: "1fr",
1711
+ sm: gridColumns === 1 ? "1fr" : gridColumns === 2 ? "repeat(2, 1fr)" : "repeat(3, 1fr)"
1712
+ },
1713
+ gap: 3
1714
+ },
1715
+ children: fieldsToRender.map((field) => {
1716
+ const shouldTakeFullWidth = fullWidthFieldTypes.includes(field.type);
1717
+ return /* @__PURE__ */ jsx(
1718
+ Box,
1719
+ {
1720
+ sx: {
1721
+ gridColumn: shouldTakeFullWidth ? {
1722
+ xs: "1 / -1",
1723
+ sm: "1 / -1"
1724
+ } : "auto"
1725
+ },
1726
+ children: /* @__PURE__ */ jsx(
1727
+ FieldRenderer,
1728
+ {
1729
+ field,
1730
+ control,
1731
+ errors,
1732
+ setValue,
1733
+ formSchema,
1734
+ uploadingFiles,
1735
+ setUploadingFiles,
1736
+ setError,
1737
+ clearErrors,
1738
+ services
1739
+ }
1740
+ )
1741
+ },
1742
+ field.name
1743
+ );
1744
+ })
1745
+ }
1746
+ );
1747
+ })(),
1748
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 2, sx: { mt: 3 }, justifyContent: "space-between", children: [
1749
+ /* @__PURE__ */ jsx(
1750
+ Button,
1751
+ {
1752
+ type: "submit",
1753
+ variant: "contained",
1754
+ size: "small",
1755
+ sx: { minWidth: 120 },
1756
+ disabled: isLoading,
1757
+ children: isLoading ? "Submitting..." : "Submit"
1758
+ }
1759
+ ),
1760
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 2, children: [
1761
+ /* @__PURE__ */ jsx(
1762
+ Button,
1763
+ {
1764
+ variant: "outlined",
1765
+ size: "small",
1766
+ onClick: () => {
1767
+ reset();
1768
+ clearErrors();
1769
+ setSubmitError(null);
1770
+ const sectionDisplayMode = formSchema.settings?.sectionDisplayMode || "panel";
1771
+ if (sectionDisplayMode === "stepper") {
1772
+ setActiveStep(0);
1773
+ }
1774
+ },
1775
+ disabled: isLoading,
1776
+ children: "Reset form"
1777
+ }
1778
+ ),
1779
+ onCancel && /* @__PURE__ */ jsx(
1780
+ Button,
1781
+ {
1782
+ variant: "outlined",
1783
+ size: "small",
1784
+ onClick: onCancel,
1785
+ disabled: isLoading,
1786
+ children: "Cancel"
1787
+ }
1788
+ )
1789
+ ] })
1790
+ ] })
1791
+ ] });
1792
+ };
1793
+
1794
+ export { ApiReferenceField, CKEditorField, CheckboxField, ColorField, DateTimePickerField, FieldRenderer, FieldView, FileField, FormReferenceField, FormRenderer, FormViewMode, RadioField, SelectField, SimpleSelect, TextField, ToggleField, buildFieldRules, defaultApiReferenceService, defaultDateFormatterService, defaultFileUploadService, defaultFormReferenceService, formatFileSize, getAllFields, getDefaultValue, isCKEditorAvailable, loadCKEditor, normalizeInitialValues, normalizeOptions, transformFormValues, useCKEditor, validateFile, waitForCKEditor };
1795
+ //# sourceMappingURL=index.mjs.map
1796
+ //# sourceMappingURL=index.mjs.map