funuicss 3.8.9 → 3.8.11

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/ui/form/Form.js CHANGED
@@ -100,7 +100,6 @@ var Flex_1 = __importDefault(require("../flex/Flex"));
100
100
  var Text_1 = __importDefault(require("../text/Text"));
101
101
  var pi_1 = require("react-icons/pi");
102
102
  var componentUtils_1 = require("../../utils/componentUtils");
103
- var theme_1 = require("../theme/theme");
104
103
  // Helper function to parse JSON input
105
104
  var parseJsonInput = function (input, defaultValue) {
106
105
  if (input === undefined || input === null) {
@@ -225,7 +224,7 @@ var FormRadio = function (_a) {
225
224
  label,
226
225
  required && ' *'))));
227
226
  };
228
- // Function to format WhatsApp message (unchanged)
227
+ // Function to format WhatsApp message - UPDATED with proper formatting
229
228
  var formatWhatsAppMessage = function (values, fields, header, footer) {
230
229
  // Build message lines
231
230
  var message = '';
@@ -233,15 +232,25 @@ var formatWhatsAppMessage = function (values, fields, header, footer) {
233
232
  if (header) {
234
233
  message += "".concat(header, "\n\n");
235
234
  }
236
- // Add form data
237
- var fieldLines = fields
238
- .filter(function (field) {
235
+ // Filter out empty/null/undefined values
236
+ var nonEmptyFields = fields.filter(function (field) {
239
237
  var value = values[field.name];
240
- return value !== undefined && value !== null && value !== '' &&
241
- !(Array.isArray(value) && value.length === 0) &&
242
- !(typeof value === 'boolean' && !value);
243
- })
244
- .map(function (field) {
238
+ // Skip if value is undefined, null, or empty string
239
+ if (value === undefined || value === null || value === '') {
240
+ return false;
241
+ }
242
+ // Skip if array is empty
243
+ if (Array.isArray(value) && value.length === 0) {
244
+ return false;
245
+ }
246
+ // Skip if checkbox is false
247
+ if (field.type === 'checkbox' && !field.multiple && value === false) {
248
+ return false;
249
+ }
250
+ return true;
251
+ });
252
+ // Format each field
253
+ var fieldLines = nonEmptyFields.map(function (field) {
245
254
  var value = values[field.name];
246
255
  var displayValue = value;
247
256
  // Format array values (for multiple checkboxes)
@@ -257,71 +266,98 @@ var formatWhatsAppMessage = function (values, fields, header, footer) {
257
266
  var option = field.options.find(function (opt) { return opt.value === value; });
258
267
  displayValue = option ? option.label : value;
259
268
  }
260
- return "*".concat(field.label || field.name, ":* ").concat(displayValue);
261
- })
262
- .join('\n');
263
- message += fieldLines;
269
+ // Ensure displayValue is a string and preserve spaces/newlines
270
+ displayValue = String(displayValue);
271
+ // WhatsApp formatting:
272
+ // - Field label on its own line
273
+ // - Value on next line wrapped in backticks
274
+ // - Double newline between fields for readability
275
+ return "".concat(field.label || field.name, "\n`").concat(displayValue, "`");
276
+ });
277
+ // Join with double newline for spacing
278
+ message += fieldLines.join('\n\n');
264
279
  // Add footer if provided
265
280
  if (footer) {
266
281
  message += "\n\n".concat(footer);
267
282
  }
268
283
  return encodeURIComponent(message);
269
284
  };
270
- // Main Form Component
271
- var Form = function (_a) {
272
- var fields = _a.fields, onSubmit = _a.onSubmit, _b = _a.defaultValues, defaultValues = _b === void 0 ? {} : _b, _c = _a.submitText, submitText = _c === void 0 ? 'Submit' : _c, _d = _a.submitBg, submitBg = _d === void 0 ? 'primary' : _d, submitPrefix = _a.submitPrefix, submitSuffix = _a.submitSuffix, _e = _a.resetText, resetText = _e === void 0 ? 'Reset' : _e, _f = _a.showReset, showReset = _f === void 0 ? true : _f, _g = _a.isLoading, isLoading = _g === void 0 ? false : _g, _h = _a.className, className = _h === void 0 ? '' : _h, _j = _a.layout, layout = _j === void 0 ? 'vertical' : _j, _k = _a.gap, gap = _k === void 0 ? '1.5rem' : _k, title = _a.title, titleSize = _a.titleSize, titleColor = _a.titleColor, description = _a.description, descriptionSize = _a.descriptionSize, descriptionColor = _a.descriptionColor, whatsappContact = _a.whatsappContact, width = _a.width, centered = _a.centered, whatsappHeader = _a.whatsappHeader, whatsappFooter = _a.whatsappFooter, _l = _a.fullWidth, fullWidth = _l === void 0 ? true : _l, _m = _a.variant, variant = _m === void 0 ? '' : _m;
273
- // Use theme variant
274
- var themeVariant = (0, theme_1.useVariant)().variant;
285
+ // Main Form Component - MODIFIED for submit-only validation
286
+ var Form = function (props) {
287
+ var fieldsProp = props.fields, onSubmitProp = props.onSubmit, _a = props.defaultValues, defaultValuesProp = _a === void 0 ? {} : _a, _b = props.submitText, submitTextProp = _b === void 0 ? 'Submit' : _b, _c = props.submitBg, submitBgProp = _c === void 0 ? 'primary' : _c, submitPrefixProp = props.submitPrefix, submitSuffixProp = props.submitSuffix, _d = props.resetText, resetTextProp = _d === void 0 ? 'Reset' : _d, _e = props.showReset, showResetProp = _e === void 0 ? true : _e, _f = props.isLoading, isLoadingProp = _f === void 0 ? false : _f, _g = props.className, classNameProp = _g === void 0 ? '' : _g, _h = props.layout, layoutProp = _h === void 0 ? 'vertical' : _h, _j = props.gap, gapProp = _j === void 0 ? '1.5rem' : _j, titleProp = props.title, titleSizeProp = props.titleSize, titleColorProp = props.titleColor, descriptionProp = props.description, descriptionSizeProp = props.descriptionSize, descriptionColorProp = props.descriptionColor, whatsappContactProp = props.whatsappContact, widthProp = props.width, centeredProp = props.centered, whatsappHeaderProp = props.whatsappHeader, whatsappFooterProp = props.whatsappFooter, _k = props.fullWidth, fullWidthProp = _k === void 0 ? true : _k, _l = props.variant, variant = _l === void 0 ? '' : _l;
275
288
  // Use component configuration with variant
276
289
  var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Form', variant).mergeWithLocal;
277
- // Parse JSON inputs
278
- var parsedFields = (0, react_1.useMemo)(function () { return parseJsonInput(fields, []); }, [fields]);
279
- var parsedDefaultValues = (0, react_1.useMemo)(function () { return parseJsonInput(defaultValues, {}); }, [defaultValues]);
280
- // Create local props for configuration
290
+ // Create local props object
281
291
  var localProps = {
282
- fields: parsedFields,
283
- onSubmit: onSubmit,
284
- defaultValues: parsedDefaultValues,
285
- submitText: submitText,
286
- submitBg: submitBg,
287
- submitPrefix: submitPrefix,
288
- submitSuffix: submitSuffix,
289
- resetText: resetText,
290
- showReset: showReset,
291
- isLoading: isLoading,
292
- className: className,
293
- layout: layout,
294
- gap: gap,
295
- title: title,
296
- titleSize: titleSize,
297
- titleColor: titleColor,
298
- description: description,
299
- descriptionSize: descriptionSize,
300
- descriptionColor: descriptionColor,
301
- whatsappContact: whatsappContact,
302
- width: width,
303
- centered: centered,
304
- whatsappHeader: whatsappHeader,
305
- whatsappFooter: whatsappFooter,
306
- fullWidth: fullWidth,
292
+ fields: fieldsProp,
293
+ onSubmit: onSubmitProp,
294
+ defaultValues: defaultValuesProp,
295
+ submitText: submitTextProp,
296
+ submitBg: submitBgProp,
297
+ submitPrefix: submitPrefixProp,
298
+ submitSuffix: submitSuffixProp,
299
+ resetText: resetTextProp,
300
+ showReset: showResetProp,
301
+ isLoading: isLoadingProp,
302
+ className: classNameProp,
303
+ layout: layoutProp,
304
+ gap: gapProp,
305
+ title: titleProp,
306
+ titleSize: titleSizeProp,
307
+ titleColor: titleColorProp,
308
+ description: descriptionProp,
309
+ descriptionSize: descriptionSizeProp,
310
+ descriptionColor: descriptionColorProp,
311
+ whatsappContact: whatsappContactProp,
312
+ width: widthProp,
313
+ centered: centeredProp,
314
+ whatsappHeader: whatsappHeaderProp,
315
+ whatsappFooter: whatsappFooterProp,
316
+ fullWidth: fullWidthProp,
307
317
  variant: variant,
308
318
  };
309
319
  // Merge with theme configuration
310
320
  var mergedProps = mergeWithLocal(localProps).props;
311
- // Destructure merged props with defaults
312
- var _o = mergedProps.fields, finalFields = _o === void 0 ? parsedFields : _o, _p = mergedProps.onSubmit, finalOnSubmit = _p === void 0 ? onSubmit : _p, _q = mergedProps.defaultValues, finalDefaultValues = _q === void 0 ? parsedDefaultValues : _q, _r = mergedProps.submitText, finalSubmitText = _r === void 0 ? submitText : _r, _s = mergedProps.submitBg, finalSubmitBg = _s === void 0 ? submitBg : _s, _t = mergedProps.submitPrefix, finalSubmitPrefix = _t === void 0 ? submitPrefix : _t, _u = mergedProps.submitSuffix, finalSubmitSuffix = _u === void 0 ? submitSuffix : _u, _v = mergedProps.resetText, finalResetText = _v === void 0 ? resetText : _v, _w = mergedProps.showReset, finalShowReset = _w === void 0 ? showReset : _w, _x = mergedProps.isLoading, finalIsLoading = _x === void 0 ? isLoading : _x, _y = mergedProps.className, finalClassName = _y === void 0 ? className : _y, _z = mergedProps.layout, finalLayout = _z === void 0 ? layout : _z, _0 = mergedProps.gap, finalGap = _0 === void 0 ? gap : _0, _1 = mergedProps.title, finalTitle = _1 === void 0 ? title : _1, _2 = mergedProps.titleSize, finalTitleSize = _2 === void 0 ? titleSize : _2, _3 = mergedProps.titleColor, finalTitleColor = _3 === void 0 ? titleColor : _3, _4 = mergedProps.description, finalDescription = _4 === void 0 ? description : _4, _5 = mergedProps.descriptionSize, finalDescriptionSize = _5 === void 0 ? descriptionSize : _5, _6 = mergedProps.descriptionColor, finalDescriptionColor = _6 === void 0 ? descriptionColor : _6, _7 = mergedProps.whatsappContact, finalWhatsappContact = _7 === void 0 ? whatsappContact : _7, _8 = mergedProps.width, finalWidth = _8 === void 0 ? width : _8, _9 = mergedProps.centered, finalCentered = _9 === void 0 ? centered : _9, _10 = mergedProps.whatsappHeader, finalWhatsappHeader = _10 === void 0 ? whatsappHeader : _10, _11 = mergedProps.whatsappFooter, finalWhatsappFooter = _11 === void 0 ? whatsappFooter : _11, _12 = mergedProps.fullWidth, finalFullWidth = _12 === void 0 ? fullWidth : _12;
321
+ // Destructure with proper priority: local props override config props
322
+ var fields = fieldsProp !== undefined ? fieldsProp : mergedProps.fields;
323
+ var onSubmit = onSubmitProp !== undefined ? onSubmitProp : mergedProps.onSubmit;
324
+ var defaultValues = defaultValuesProp !== undefined ? defaultValuesProp : mergedProps.defaultValues;
325
+ var submitText = submitTextProp !== undefined ? submitTextProp : mergedProps.submitText;
326
+ var submitBg = submitBgProp !== undefined ? submitBgProp : mergedProps.submitBg;
327
+ var submitPrefix = submitPrefixProp !== undefined ? submitPrefixProp : mergedProps.submitPrefix;
328
+ var submitSuffix = submitSuffixProp !== undefined ? submitSuffixProp : mergedProps.submitSuffix;
329
+ var resetText = resetTextProp !== undefined ? resetTextProp : mergedProps.resetText;
330
+ var showReset = showResetProp !== undefined ? showResetProp : mergedProps.showReset;
331
+ var isLoading = isLoadingProp !== undefined ? isLoadingProp : mergedProps.isLoading;
332
+ var className = classNameProp !== undefined ? classNameProp : mergedProps.className;
333
+ var layout = layoutProp !== undefined ? layoutProp : mergedProps.layout;
334
+ var gap = gapProp !== undefined ? gapProp : mergedProps.gap;
335
+ var title = titleProp !== undefined ? titleProp : mergedProps.title;
336
+ var titleSize = titleSizeProp !== undefined ? titleSizeProp : mergedProps.titleSize;
337
+ var titleColor = titleColorProp !== undefined ? titleColorProp : mergedProps.titleColor;
338
+ var description = descriptionProp !== undefined ? descriptionProp : mergedProps.description;
339
+ var descriptionSize = descriptionSizeProp !== undefined ? descriptionSizeProp : mergedProps.descriptionSize;
340
+ var descriptionColor = descriptionColorProp !== undefined ? descriptionColorProp : mergedProps.descriptionColor;
341
+ var whatsappContact = whatsappContactProp !== undefined ? whatsappContactProp : mergedProps.whatsappContact;
342
+ var width = widthProp !== undefined ? widthProp : mergedProps.width;
343
+ var centered = centeredProp !== undefined ? centeredProp : mergedProps.centered;
344
+ var whatsappHeader = whatsappHeaderProp !== undefined ? whatsappHeaderProp : mergedProps.whatsappHeader;
345
+ var whatsappFooter = whatsappFooterProp !== undefined ? whatsappFooterProp : mergedProps.whatsappFooter;
346
+ var fullWidth = fullWidthProp !== undefined ? fullWidthProp : mergedProps.fullWidth;
347
+ // Parse JSON inputs
348
+ var parsedFields = (0, react_1.useMemo)(function () { return parseJsonInput(fields, []); }, [fields]);
349
+ var parsedDefaultValues = (0, react_1.useMemo)(function () { return parseJsonInput(defaultValues, {}); }, [defaultValues]);
313
350
  // State management
314
- var _13 = (0, react_1.useState)({}), errors = _13[0], setErrors = _13[1];
315
- var _14 = (0, react_1.useState)({}), touched = _14[0], setTouched = _14[1];
316
- var _15 = (0, react_1.useState)(function () {
351
+ var _m = (0, react_1.useState)({}), errors = _m[0], setErrors = _m[1];
352
+ var _o = (0, react_1.useState)(function () {
317
353
  // Initialize form values from defaultValues and field values
318
354
  var initialValues = {};
319
- finalFields.forEach(function (field) {
355
+ parsedFields.forEach(function (field) {
320
356
  if (field.value !== undefined) {
321
357
  initialValues[field.name] = field.value;
322
358
  }
323
- else if (finalDefaultValues[field.name] !== undefined) {
324
- initialValues[field.name] = finalDefaultValues[field.name];
359
+ else if (parsedDefaultValues[field.name] !== undefined) {
360
+ initialValues[field.name] = parsedDefaultValues[field.name];
325
361
  }
326
362
  else {
327
363
  // Set default empty values
@@ -337,15 +373,16 @@ var Form = function (_a) {
337
373
  }
338
374
  });
339
375
  return initialValues;
340
- }), formValues = _15[0], setFormValues = _15[1];
341
- var _16 = (0, react_1.useState)(false), isSubmitting = _16[0], setIsSubmitting = _16[1];
376
+ }), formValues = _o[0], setFormValues = _o[1];
377
+ var _p = (0, react_1.useState)(false), isSubmitting = _p[0], setIsSubmitting = _p[1];
378
+ var _q = (0, react_1.useState)(false), hasBeenSubmitted = _q[0], setHasBeenSubmitted = _q[1];
342
379
  // Update form values when defaultValues prop changes
343
380
  (0, react_1.useEffect)(function () {
344
- if (Object.keys(finalDefaultValues).length > 0) {
345
- setFormValues(function (prev) { return (__assign(__assign({}, prev), finalDefaultValues)); });
381
+ if (Object.keys(parsedDefaultValues).length > 0) {
382
+ setFormValues(function (prev) { return (__assign(__assign({}, prev), parsedDefaultValues)); });
346
383
  }
347
- }, [finalDefaultValues]);
348
- // Validate a single field (unchanged)
384
+ }, [parsedDefaultValues]);
385
+ // Validate a single field
349
386
  var validateField = (0, react_1.useCallback)(function (field, value) {
350
387
  var _a, _b, _c, _d, _e;
351
388
  // Required validation
@@ -426,11 +463,11 @@ var Form = function (_a) {
426
463
  }
427
464
  return null;
428
465
  }, []);
429
- // Validate form (unchanged)
466
+ // Validate form
430
467
  var validateForm = (0, react_1.useCallback)(function () {
431
468
  var newErrors = {};
432
469
  var hasErrors = false;
433
- finalFields.forEach(function (field) {
470
+ parsedFields.forEach(function (field) {
434
471
  var value = formValues[field.name];
435
472
  var error = validateField(field, value);
436
473
  if (error) {
@@ -439,102 +476,46 @@ var Form = function (_a) {
439
476
  }
440
477
  });
441
478
  setErrors(newErrors);
479
+ setHasBeenSubmitted(true);
442
480
  return !hasErrors;
443
- }, [finalFields, validateField, formValues]);
444
- // Handle field change for checkboxes and radios (unchanged)
481
+ }, [parsedFields, validateField, formValues]);
482
+ // Handle field change for checkboxes and radios
445
483
  var handleFieldChange = (0, react_1.useCallback)(function (fieldName, newValue) {
446
484
  // Update form values
447
485
  setFormValues(function (prev) {
448
486
  var _a;
449
487
  return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = newValue, _a)));
450
488
  });
451
- // Update touched state
452
- setTouched(function (prev) {
453
- var _a;
454
- return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
455
- });
456
- // Validate the changed field
457
- var field = finalFields.find(function (f) { return f.name === fieldName; });
458
- if (!field)
459
- return;
460
- var error = validateField(field, newValue);
489
+ // Clear error for this field when user makes a change
461
490
  setErrors(function (prev) {
462
- var _a;
463
- if (error) {
464
- return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
465
- }
466
- else {
467
- var newErrors = __assign({}, prev);
468
- delete newErrors[fieldName];
469
- return newErrors;
470
- }
491
+ var newErrors = __assign({}, prev);
492
+ delete newErrors[fieldName];
493
+ return newErrors;
471
494
  });
472
- }, [finalFields, validateField]);
473
- // Handle input field change (unchanged)
474
- var handleInputChange = (0, react_1.useCallback)(function (fieldName, value) {
495
+ }, []);
496
+ // Handle input change - NO VALIDATION ON CHANGE
497
+ var handleInputEventChange = (0, react_1.useCallback)(function (e) {
498
+ var fieldName = e.target.name;
499
+ var value = e.target.value;
475
500
  // Update form values
476
501
  setFormValues(function (prev) {
477
502
  var _a;
478
503
  return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = value, _a)));
479
504
  });
480
- // Update touched state
481
- setTouched(function (prev) {
482
- var _a;
483
- return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
484
- });
485
- // Validate the changed field
486
- var field = finalFields.find(function (f) { return f.name === fieldName; });
487
- if (!field)
488
- return;
489
- var error = validateField(field, value);
505
+ // Clear error for this field when user makes a change
490
506
  setErrors(function (prev) {
491
- var _a;
492
- if (error) {
493
- return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
494
- }
495
- else {
496
- var newErrors = __assign({}, prev);
497
- delete newErrors[fieldName];
498
- return newErrors;
499
- }
500
- });
501
- }, [finalFields, validateField]);
502
- // Handle field blur (unchanged)
503
- var handleFieldBlur = (0, react_1.useCallback)(function (fieldName) {
504
- setTouched(function (prev) {
505
- var _a;
506
- return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
507
+ var newErrors = __assign({}, prev);
508
+ delete newErrors[fieldName];
509
+ return newErrors;
507
510
  });
508
- // Validate the field
509
- var field = finalFields.find(function (f) { return f.name === fieldName; });
510
- if (!field)
511
- return;
512
- var value = formValues[fieldName];
513
- var error = validateField(field, value);
514
- setErrors(function (prev) {
515
- var _a;
516
- if (error) {
517
- return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
518
- }
519
- else {
520
- var newErrors = __assign({}, prev);
521
- delete newErrors[fieldName];
522
- return newErrors;
523
- }
524
- });
525
- }, [finalFields, validateField, formValues]);
526
- // Handle form submission (unchanged)
511
+ }, []);
512
+ // Handle form submission
527
513
  var handleSubmit = (0, react_1.useCallback)(function (e) { return __awaiter(void 0, void 0, void 0, function () {
528
- var allTouched, isValid, firstErrorField, element, message, cleanPhone, whatsappUrl, error_1;
514
+ var isValid, firstErrorField, element, message, cleanPhone, whatsappUrl, error_1;
529
515
  return __generator(this, function (_a) {
530
516
  switch (_a.label) {
531
517
  case 0:
532
518
  e.preventDefault();
533
- allTouched = {};
534
- finalFields.forEach(function (field) {
535
- allTouched[field.name] = true;
536
- });
537
- setTouched(allTouched);
538
519
  isValid = validateForm();
539
520
  if (!isValid) {
540
521
  firstErrorField = Object.keys(errors)[0];
@@ -549,20 +530,20 @@ var Form = function (_a) {
549
530
  _a.label = 1;
550
531
  case 1:
551
532
  _a.trys.push([1, 7, 8, 9]);
552
- if (!finalWhatsappContact) return [3 /*break*/, 4];
553
- message = formatWhatsAppMessage(formValues, finalFields, finalWhatsappHeader, finalWhatsappFooter);
554
- cleanPhone = finalWhatsappContact.replace(/[\s+\-()]/g, '');
533
+ if (!whatsappContact) return [3 /*break*/, 4];
534
+ message = formatWhatsAppMessage(formValues, parsedFields, whatsappHeader, whatsappFooter);
535
+ cleanPhone = whatsappContact.replace(/[\s+\-()]/g, '');
555
536
  whatsappUrl = "https://wa.me/".concat(cleanPhone, "?text=").concat(message);
556
537
  window.open(whatsappUrl, '_blank');
557
- if (!finalOnSubmit) return [3 /*break*/, 3];
558
- return [4 /*yield*/, finalOnSubmit(formValues, true)];
538
+ if (!onSubmit) return [3 /*break*/, 3];
539
+ return [4 /*yield*/, onSubmit(formValues, true)];
559
540
  case 2:
560
541
  _a.sent();
561
542
  _a.label = 3;
562
543
  case 3: return [3 /*break*/, 6];
563
544
  case 4:
564
- if (!finalOnSubmit) return [3 /*break*/, 6];
565
- return [4 /*yield*/, finalOnSubmit(formValues, false)];
545
+ if (!onSubmit) return [3 /*break*/, 6];
546
+ return [4 /*yield*/, onSubmit(formValues, false)];
566
547
  case 5:
567
548
  _a.sent();
568
549
  _a.label = 6;
@@ -578,17 +559,17 @@ var Form = function (_a) {
578
559
  case 9: return [2 /*return*/];
579
560
  }
580
561
  });
581
- }); }, [finalFields, validateForm, formValues, finalWhatsappContact, finalWhatsappHeader, finalWhatsappFooter, finalOnSubmit, errors]);
582
- // Handle form reset (unchanged)
562
+ }); }, [validateForm, formValues, whatsappContact, whatsappHeader, whatsappFooter, onSubmit, errors, parsedFields]);
563
+ // Handle form reset
583
564
  var handleReset = (0, react_1.useCallback)(function () {
584
565
  // Reset to initial values
585
566
  var initialValues = {};
586
- finalFields.forEach(function (field) {
567
+ parsedFields.forEach(function (field) {
587
568
  if (field.value !== undefined) {
588
569
  initialValues[field.name] = field.value;
589
570
  }
590
- else if (finalDefaultValues[field.name] !== undefined) {
591
- initialValues[field.name] = finalDefaultValues[field.name];
571
+ else if (parsedDefaultValues[field.name] !== undefined) {
572
+ initialValues[field.name] = parsedDefaultValues[field.name];
592
573
  }
593
574
  else {
594
575
  if (field.type === 'checkbox' && field.multiple) {
@@ -604,49 +585,36 @@ var Form = function (_a) {
604
585
  });
605
586
  setFormValues(initialValues);
606
587
  setErrors({});
607
- setTouched({});
608
- }, [finalFields, finalDefaultValues]);
609
- // Get field status for Input component (unchanged)
588
+ setHasBeenSubmitted(false);
589
+ }, [parsedFields, parsedDefaultValues]);
590
+ // Get field status for Input component
610
591
  var getFieldStatus = (0, react_1.useCallback)(function (fieldName) {
611
592
  var error = errors[fieldName];
612
- var isTouched = touched[fieldName];
613
- if (error)
593
+ // Only show validation status if form has been submitted and there's an error
594
+ if (hasBeenSubmitted && error) {
614
595
  return 'danger';
615
- if (isTouched && !error && formValues[fieldName] !== '') {
616
- return 'success';
617
596
  }
618
597
  return undefined;
619
- }, [errors, touched, formValues]);
620
- // Check if form is valid for submission (unchanged)
598
+ }, [errors, hasBeenSubmitted]);
599
+ // Check if form is valid for submission
621
600
  var isFormValid = (0, react_1.useMemo)(function () {
622
- // Check if any required fields are empty
623
- var hasEmptyRequiredFields = finalFields.some(function (field) {
624
- if (!field.required)
625
- return false;
626
- var value = formValues[field.name];
627
- if (field.type === 'checkbox' && field.multiple) {
628
- return !Array.isArray(value) || value.length === 0;
629
- }
630
- if (field.type === 'checkbox') {
631
- return value === false;
632
- }
633
- return !value || value === '';
634
- });
635
- // Check if there are any validation errors
636
- var hasValidationErrors = Object.keys(errors).length > 0;
637
- return !hasEmptyRequiredFields && !hasValidationErrors;
638
- }, [finalFields, formValues, errors]);
639
- // Submit button disabled state (unchanged)
640
- var isSubmitDisabled = isSubmitting || finalIsLoading || !isFormValid;
641
- // Check if WhatsApp is configured (unchanged)
642
- var hasWhatsApp = !!finalWhatsappContact;
643
- // Render field based on type (unchanged)
601
+ // Only check validity when form has been submitted
602
+ if (hasBeenSubmitted) {
603
+ return Object.keys(errors).length === 0;
604
+ }
605
+ // If form hasn't been submitted yet, consider it valid
606
+ return true;
607
+ }, [hasBeenSubmitted, errors]);
608
+ // Submit button disabled state
609
+ var isSubmitDisabled = isSubmitting || isLoading;
610
+ // Check if WhatsApp is configured
611
+ var hasWhatsApp = !!whatsappContact;
612
+ // Render field based on type
644
613
  var renderField = (0, react_1.useCallback)(function (field) {
645
614
  var _a, _b, _c, _d, _e;
646
615
  var status = getFieldStatus(field.name);
647
616
  var error = errors[field.name];
648
- var isTouched = touched[field.name];
649
- var showError = error && isTouched;
617
+ var showError = hasBeenSubmitted && error;
650
618
  var value = formValues[field.name];
651
619
  // Field wrapper classes
652
620
  var wrapperClass = "col min-w-200 field ".concat(showError ? 'field-error' : '').trim();
@@ -655,7 +623,7 @@ var Form = function (_a) {
655
623
  // Generate unique ID for the input
656
624
  var inputId = ((_a = field.inputProps) === null || _a === void 0 ? void 0 : _a.id) || "form-field-".concat(field.name);
657
625
  // Base props for Input component
658
- var baseProps = __assign({ id: inputId, name: field.name, label: field.label, placeholder: field.placeholder, helperText: helperText, disabled: field.disabled || finalIsLoading, fullWidth: finalFullWidth }, field.inputProps);
626
+ var baseProps = __assign({ id: inputId, name: field.name, label: field.label, placeholder: field.placeholder, helperText: helperText, disabled: field.disabled || isLoading, fullWidth: fullWidth }, field.inputProps);
659
627
  // Only add status if it's not undefined
660
628
  if (status !== undefined) {
661
629
  baseProps.status = status;
@@ -682,13 +650,13 @@ var Form = function (_a) {
682
650
  var newValues = checkedValues_1.filter(function (v) { return v !== option.value; });
683
651
  handleFieldChange(field.name, newValues);
684
652
  }
685
- }, disabled: field.disabled || option.disabled || finalIsLoading, required: field.required && index === 0, value: option.value }));
653
+ }, disabled: field.disabled || option.disabled || isLoading, required: field.required && index === 0, value: option.value }));
686
654
  }))));
687
655
  }
688
656
  else {
689
657
  // Single checkbox (boolean)
690
658
  return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
691
- react_1.default.createElement(FormCheckbox, { label: field.label, checked: !!value, onChange: function (checked) { return handleFieldChange(field.name, checked); }, disabled: field.disabled || finalIsLoading, required: field.required, id: inputId })));
659
+ react_1.default.createElement(FormCheckbox, { label: field.label, checked: !!value, onChange: function (checked) { return handleFieldChange(field.name, checked); }, disabled: field.disabled || isLoading, required: field.required, id: inputId })));
692
660
  }
693
661
  case 'radio':
694
662
  if (!((_c = field.options) === null || _c === void 0 ? void 0 : _c.length))
@@ -696,29 +664,999 @@ var Form = function (_a) {
696
664
  return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
697
665
  field.label && (react_1.default.createElement("div", { className: "form-label", style: { marginBottom: '0.5rem' } },
698
666
  react_1.default.createElement(Text_1.default, { text: field.label + (field.required ? ' *' : ''), size: "sm", color: "text", bold: true }))),
699
- react_1.default.createElement(Flex_1.default, { direction: "column", gap: "0.5rem" }, field.options.map(function (option, index) { return (react_1.default.createElement(FormRadio, { key: "".concat(field.name, "_").concat(index), id: "".concat(inputId, "_").concat(index), label: option.label, checked: value === option.value, onChange: function () { return handleFieldChange(field.name, option.value); }, disabled: field.disabled || option.disabled || finalIsLoading, required: field.required && index === 0, value: option.value })); }))));
667
+ react_1.default.createElement(Flex_1.default, { direction: "column", gap: "0.5rem" }, field.options.map(function (option, index) { return (react_1.default.createElement(FormRadio, { key: "".concat(field.name, "_").concat(index), id: "".concat(inputId, "_").concat(index), label: option.label, checked: value === option.value, onChange: function () { return handleFieldChange(field.name, option.value); }, disabled: field.disabled || option.disabled || isLoading, required: field.required && index === 0, value: option.value })); }))));
700
668
  case 'textarea':
701
669
  return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
702
- react_1.default.createElement(Input_1.default, __assign({ multiline: true, rows: ((_d = field.inputProps) === null || _d === void 0 ? void 0 : _d.rows) || 4, value: value || '', onChange: function (e) { return handleInputChange(field.name, e.target.value); }, onBlur: function () { return handleFieldBlur(field.name); } }, baseProps))));
670
+ react_1.default.createElement(Input_1.default, __assign({ multiline: true, rows: ((_d = field.inputProps) === null || _d === void 0 ? void 0 : _d.rows) || 4, value: value || '', onChange: handleInputEventChange }, baseProps))));
703
671
  case 'select':
704
672
  return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
705
- react_1.default.createElement(Input_1.default, __assign({ select: true, options: ((_e = field.options) === null || _e === void 0 ? void 0 : _e.map(function (opt) { return ({ text: opt.label, value: opt.value }); })) || [], value: value || '', onChange: function (e) { return handleInputChange(field.name, e.target.value); }, onBlur: function () { return handleFieldBlur(field.name); } }, baseProps))));
673
+ react_1.default.createElement(Input_1.default, __assign({ select: true, options: ((_e = field.options) === null || _e === void 0 ? void 0 : _e.map(function (opt) { return ({ text: opt.label, value: opt.value }); })) || [], value: value || '', onChange: handleInputEventChange }, baseProps))));
706
674
  default:
707
675
  // text, email, number, tel, date, file, password
708
676
  return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
709
- react_1.default.createElement(Input_1.default, __assign({ type: field.type, value: value || '', onChange: function (e) { return handleInputChange(field.name, e.target.value); }, onBlur: function () { return handleFieldBlur(field.name); } }, baseProps))));
677
+ react_1.default.createElement(Input_1.default, __assign({ type: field.type, value: value || '', onChange: handleInputEventChange }, baseProps))));
710
678
  }
711
- }, [errors, touched, formValues, finalIsLoading, getFieldStatus, handleFieldChange, handleInputChange, handleFieldBlur, finalFullWidth]);
712
- return (react_1.default.createElement("div", { className: "form-wrapper ".concat(finalCentered ? 'center' : '', " ").concat(finalClassName), style: { width: "100%", maxWidth: finalWidth || "450px" } },
713
- finalTitle && (react_1.default.createElement("div", { className: "form-header", style: { marginBottom: '2rem' } },
714
- react_1.default.createElement(Text_1.default, { text: finalTitle, size: finalTitleSize || "3xl", color: finalTitleColor || "", block: true }),
715
- finalDescription && (react_1.default.createElement(Text_1.default, { article: true, size: finalDescriptionSize || "sm", color: finalDescriptionColor || "" },
716
- react_1.default.createElement("div", { className: "article text-sm", dangerouslySetInnerHTML: { __html: finalDescription } }))))),
679
+ }, [errors, hasBeenSubmitted, formValues, isLoading, getFieldStatus, handleFieldChange, handleInputEventChange, fullWidth]);
680
+ // Don't render if no fields are configured
681
+ if (parsedFields.length === 0) {
682
+ console.warn('Form: No fields configured. Please provide fields prop or configure via theme.');
683
+ return null;
684
+ }
685
+ return (react_1.default.createElement("div", { className: "form-wrapper ".concat(centered ? 'center' : '', " ").concat(className), style: { width: "100%", maxWidth: width || "450px" } },
686
+ title && (react_1.default.createElement("div", { className: "form-header", style: { marginBottom: '2rem' } },
687
+ react_1.default.createElement(Text_1.default, { text: title, size: titleSize || "3xl", color: titleColor || "", block: true }),
688
+ description && (react_1.default.createElement(Text_1.default, { article: true, size: descriptionSize || "sm", color: descriptionColor || "" },
689
+ react_1.default.createElement("div", { className: "article text-sm", dangerouslySetInnerHTML: { __html: description } }))))),
717
690
  react_1.default.createElement("form", { className: "form", onSubmit: handleSubmit, style: { width: '100%' } },
718
- react_1.default.createElement(Flex_1.default, { direction: finalLayout === 'horizontal' ? 'row' : 'column', gap: finalGap, width: '100%' }, finalFields.map(renderField)),
719
- react_1.default.createElement(Flex_1.default, { direction: "column", gap: "1rem", style: { marginTop: '2rem', width: finalFullWidth ? '100%' : undefined } },
720
- react_1.default.createElement(Button_1.default, { type: "submit", text: hasWhatsApp ? "Send via WhatsApp" : finalSubmitText, bg: finalSubmitBg || "primary", raised: true, prefix: finalSubmitPrefix || hasWhatsApp ? react_1.default.createElement(pi_1.PiWhatsappLogo, null) : react_1.default.createElement(pi_1.PiPaperPlaneTilt, null), suffix: finalSubmitSuffix,
721
- // startIcon={hasWhatsApp ? <PiWhatsappLogo /> : <PiPaperPlaneTilt />}
722
- disabled: isSubmitDisabled, isLoading: isSubmitting || finalIsLoading, fullWidth: finalFullWidth })))));
691
+ react_1.default.createElement(Flex_1.default, { direction: layout === 'horizontal' ? 'row' : 'column', gap: gap, width: '100%' }, parsedFields.map(renderField)),
692
+ react_1.default.createElement(Flex_1.default, { direction: "column", gap: "1rem", style: { marginTop: '2rem', width: fullWidth ? '100%' : undefined } },
693
+ react_1.default.createElement(Button_1.default, { type: "submit", text: hasWhatsApp ? "Send via WhatsApp" : submitText, bg: submitBg || "primary", raised: true, prefix: submitPrefix || hasWhatsApp ? react_1.default.createElement(pi_1.PiWhatsappLogo, null) : react_1.default.createElement(pi_1.PiPaperPlaneTilt, null), suffix: submitSuffix, disabled: isSubmitDisabled, isLoading: isSubmitting || isLoading, fullWidth: fullWidth })))));
723
694
  };
724
695
  exports.default = Form;
696
+ // 'use client';
697
+ // import React, { useState, useEffect, useCallback, useMemo } from 'react';
698
+ // import Button from '../button/Button';
699
+ // import Input from '../input/Input';
700
+ // import Flex from '../flex/Flex';
701
+ // import Text from '../text/Text';
702
+ // import { PiPaperPlaneTilt, PiWarningCircle, PiWhatsappLogo } from 'react-icons/pi';
703
+ // import { useComponentConfiguration } from '../../utils/componentUtils';
704
+ // import { useVariant } from '../theme/theme';
705
+ // // Field types supported
706
+ // export type InputType =
707
+ // | 'text'
708
+ // | 'email'
709
+ // | 'number'
710
+ // | 'tel'
711
+ // | 'textarea'
712
+ // | 'password'
713
+ // | 'date'
714
+ // | 'select'
715
+ // | 'checkbox'
716
+ // | 'radio'
717
+ // | 'file';
718
+ // // Field option
719
+ // export interface FieldOption {
720
+ // label: string;
721
+ // value: string;
722
+ // disabled?: boolean;
723
+ // }
724
+ // // Simplified field configuration
725
+ // export interface FormField {
726
+ // name: string;
727
+ // label?: string;
728
+ // type: InputType;
729
+ // required?: boolean;
730
+ // placeholder?: string;
731
+ // options?: FieldOption[];
732
+ // multiple?: boolean; // For checkboxes
733
+ // value?: any; // Initial value
734
+ // disabled?: boolean;
735
+ // helperText?: string;
736
+ // // Input component props (passed directly to Input)
737
+ // inputProps?: {
738
+ // startIcon?: React.ReactNode;
739
+ // endIcon?: React.ReactNode;
740
+ // prefix?: React.ReactNode;
741
+ // suffix?: React.ReactNode;
742
+ // stringPrefix?: string;
743
+ // stringSuffix?: string;
744
+ // iconicBg?: string;
745
+ // funcss?: string;
746
+ // bg?: string;
747
+ // flat?: boolean;
748
+ // bordered?: boolean;
749
+ // borderless?: boolean;
750
+ // rounded?: boolean;
751
+ // leftRounded?: boolean;
752
+ // rightRounded?: boolean;
753
+ // rows?: number;
754
+ // noBorder?: boolean;
755
+ // variant?: string;
756
+ // // Standard HTML attributes
757
+ // id?: string;
758
+ // autocomplete?: string;
759
+ // pattern?: string;
760
+ // min?: string | number;
761
+ // max?: string | number;
762
+ // minLength?: number;
763
+ // maxLength?: number;
764
+ // step?: string | number;
765
+ // };
766
+ // }
767
+ // // Form props
768
+ // export interface FormProps {
769
+ // fields?: FormField[] | string; // Allow string (JSON) or array
770
+ // onSubmit?: (values: Record<string, any>, viaWhatsApp?: boolean) => void;
771
+ // defaultValues?: Record<string, any> | string; // Allow string (JSON) or object
772
+ // submitText?: string;
773
+ // submitBg?: string;
774
+ // submitPrefix?: React.ReactNode | string;
775
+ // submitSuffix?: React.ReactNode | string;
776
+ // resetText?: string;
777
+ // showReset?: boolean;
778
+ // isLoading?: boolean;
779
+ // className?: string;
780
+ // layout?: 'vertical' | 'horizontal';
781
+ // gap?: number | string;
782
+ // title?: string;
783
+ // titleSize?: string;
784
+ // titleColor?: string;
785
+ // description?: string;
786
+ // descriptionSize?: string;
787
+ // descriptionColor?: string;
788
+ // // WhatsApp props (simple, not object)
789
+ // whatsappContact?: string;
790
+ // whatsappHeader?: string;
791
+ // whatsappFooter?: string;
792
+ // // New props for fullWidth
793
+ // fullWidth?: boolean;
794
+ // width?: string;
795
+ // centered?: boolean;
796
+ // // Variant support
797
+ // variant?: string;
798
+ // }
799
+ // // Helper function to parse JSON input
800
+ // const parseJsonInput = <T,>(input: T | string | undefined, defaultValue: T): T => {
801
+ // if (input === undefined || input === null) {
802
+ // return defaultValue;
803
+ // }
804
+ // // If it's already the correct type, return as is
805
+ // if (typeof input !== 'string') {
806
+ // return input;
807
+ // }
808
+ // try {
809
+ // // Try to parse as JSON
810
+ // const parsed = JSON.parse(input);
811
+ // return parsed;
812
+ // } catch (error) {
813
+ // console.warn('Failed to parse JSON input:', input, error);
814
+ // // If parsing fails, try to interpret as a string that might be valid
815
+ // try {
816
+ // // Try to handle common cases like arrays or objects without quotes
817
+ // const trimmed = input.trim();
818
+ // if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
819
+ // return JSON.parse(trimmed);
820
+ // } else if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
821
+ // return JSON.parse(trimmed);
822
+ // }
823
+ // } catch (e) {
824
+ // // If still fails, return default
825
+ // }
826
+ // return defaultValue;
827
+ // }
828
+ // };
829
+ // // Custom Checkbox Component (unchanged)
830
+ // const FormCheckbox: React.FC<{
831
+ // label?: string;
832
+ // checked: boolean;
833
+ // onChange: (checked: boolean) => void;
834
+ // disabled?: boolean;
835
+ // required?: boolean;
836
+ // value?: string;
837
+ // id?: string;
838
+ // }> = ({ label, checked, onChange, disabled, required, value, id }) => {
839
+ // return (
840
+ // <label
841
+ // className="funui_form-checkbox"
842
+ // style={{
843
+ // display: 'flex',
844
+ // alignItems: 'center',
845
+ // gap: '0.5rem',
846
+ // cursor: disabled ? 'not-allowed' : 'pointer',
847
+ // userSelect: 'none',
848
+ // width: 'fit-content',
849
+ // padding: '0.25rem 0',
850
+ // }}
851
+ // >
852
+ // <input
853
+ // type="checkbox"
854
+ // id={id}
855
+ // checked={checked}
856
+ // onChange={(e) => !disabled && onChange(e.target.checked)}
857
+ // disabled={disabled}
858
+ // required={required}
859
+ // value={value}
860
+ // style={{
861
+ // position: 'absolute',
862
+ // opacity: 0,
863
+ // width: 0,
864
+ // height: 0,
865
+ // pointerEvents: 'none'
866
+ // }}
867
+ // />
868
+ // <div
869
+ // className="funui_form-checkbox-box"
870
+ // style={{
871
+ // width: '1.25rem',
872
+ // height: '1.25rem',
873
+ // border: checked ? '2px solid var(--primary)' : '2px solid var(--borderColor)',
874
+ // borderRadius: '0.25rem',
875
+ // backgroundColor: checked ? 'var(--primary)' : 'transparent',
876
+ // position: 'relative',
877
+ // transition: 'all 0.2s ease',
878
+ // display: 'flex',
879
+ // alignItems: 'center',
880
+ // justifyContent: 'center',
881
+ // flexShrink: 0,
882
+ // }}
883
+ // >
884
+ // {checked && (
885
+ // <svg
886
+ // width="14"
887
+ // height="14"
888
+ // viewBox="0 0 14 14"
889
+ // fill="none"
890
+ // xmlns="http://www.w3.org2000/svg"
891
+ // style={{
892
+ // stroke: 'white',
893
+ // strokeWidth: '2',
894
+ // strokeLinecap: 'round',
895
+ // strokeLinejoin: 'round',
896
+ // }}
897
+ // >
898
+ // <path d="M3 7L6 10L11 4" />
899
+ // </svg>
900
+ // )}
901
+ // </div>
902
+ // {label && (
903
+ // <span
904
+ // className="funui_form-checkbox-label"
905
+ // style={{
906
+ // fontSize: '0.875rem',
907
+ // color: disabled ? 'var(--text-muted)' : 'var(--text)',
908
+ // fontWeight: checked ? '500' : '400',
909
+ // }}
910
+ // >
911
+ // {label}{required && ' *'}
912
+ // </span>
913
+ // )}
914
+ // </label>
915
+ // );
916
+ // };
917
+ // // Custom Radio Component (unchanged)
918
+ // const FormRadio: React.FC<{
919
+ // label?: string;
920
+ // checked: boolean;
921
+ // onChange: (checked: boolean) => void;
922
+ // disabled?: boolean;
923
+ // required?: boolean;
924
+ // value?: string;
925
+ // id?: string;
926
+ // }> = ({ label, checked, onChange, disabled, required, value, id }) => {
927
+ // return (
928
+ // <label
929
+ // className="funui_form-radio"
930
+ // style={{
931
+ // display: 'flex',
932
+ // alignItems: 'center',
933
+ // gap: '0.5rem',
934
+ // cursor: disabled ? 'not-allowed' : 'pointer',
935
+ // userSelect: 'none',
936
+ // width: 'fit-content',
937
+ // padding: '0.25rem 0',
938
+ // }}
939
+ // >
940
+ // <input
941
+ // type="radio"
942
+ // id={id}
943
+ // checked={checked}
944
+ // onChange={(e) => !disabled && onChange(e.target.checked)}
945
+ // disabled={disabled}
946
+ // required={required}
947
+ // value={value}
948
+ // style={{
949
+ // position: 'absolute',
950
+ // opacity: 0,
951
+ // width: 0,
952
+ // height: 0,
953
+ // pointerEvents: 'none'
954
+ // }}
955
+ // />
956
+ // <div
957
+ // className="funui_form-radio-circle"
958
+ // style={{
959
+ // width: '1.25rem',
960
+ // height: '1.25rem',
961
+ // border: checked ? '2px solid var(--primary)' : '2px solid var(--borderColor)',
962
+ // borderRadius: '50%',
963
+ // backgroundColor: 'transparent',
964
+ // position: 'relative',
965
+ // transition: 'all 0.2s ease',
966
+ // display: 'flex',
967
+ // alignItems: 'center',
968
+ // justifyContent: 'center',
969
+ // flexShrink: 0,
970
+ // }}
971
+ // >
972
+ // {checked && (
973
+ // <div
974
+ // style={{
975
+ // width: '0.75rem',
976
+ // height: '0.75rem',
977
+ // backgroundColor: 'var(--primary)',
978
+ // borderRadius: '50%',
979
+ // }}
980
+ // />
981
+ // )}
982
+ // </div>
983
+ // {label && (
984
+ // <span
985
+ // className="funui_form-radio-label"
986
+ // style={{
987
+ // fontSize: '0.875rem',
988
+ // color: disabled ? 'var(--text-muted)' : 'var(--text)',
989
+ // fontWeight: checked ? '500' : '400',
990
+ // }}
991
+ // >
992
+ // {label}{required && ' *'}
993
+ // </span>
994
+ // )}
995
+ // </label>
996
+ // );
997
+ // };
998
+ // // Function to format WhatsApp message - UPDATED with proper formatting
999
+ // const formatWhatsAppMessage = (
1000
+ // values: Record<string, any>,
1001
+ // fields: FormField[],
1002
+ // header?: string,
1003
+ // footer?: string
1004
+ // ): string => {
1005
+ // // Build message lines
1006
+ // let message = '';
1007
+ // // Add header if provided
1008
+ // if (header) {
1009
+ // message += `${header}\n\n`;
1010
+ // }
1011
+ // // Filter out empty/null/undefined values
1012
+ // const nonEmptyFields = fields.filter(field => {
1013
+ // const value = values[field.name];
1014
+ // // Skip if value is undefined, null, or empty string
1015
+ // if (value === undefined || value === null || value === '') {
1016
+ // return false;
1017
+ // }
1018
+ // // Skip if array is empty
1019
+ // if (Array.isArray(value) && value.length === 0) {
1020
+ // return false;
1021
+ // }
1022
+ // // Skip if checkbox is false
1023
+ // if (field.type === 'checkbox' && !field.multiple && value === false) {
1024
+ // return false;
1025
+ // }
1026
+ // return true;
1027
+ // });
1028
+ // // Format each field
1029
+ // const fieldLines = nonEmptyFields.map(field => {
1030
+ // const value = values[field.name];
1031
+ // let displayValue = value;
1032
+ // // Format array values (for multiple checkboxes)
1033
+ // if (Array.isArray(value)) {
1034
+ // displayValue = value.join(', ');
1035
+ // }
1036
+ // // Format checkbox values
1037
+ // if (field.type === 'checkbox' && !field.multiple) {
1038
+ // displayValue = value ? 'Yes' : 'No';
1039
+ // }
1040
+ // // Format select/radio values
1041
+ // if ((field.type === 'select' || field.type === 'radio') && field.options) {
1042
+ // const option = field.options.find(opt => opt.value === value);
1043
+ // displayValue = option ? option.label : value;
1044
+ // }
1045
+ // // Ensure displayValue is a string and preserve spaces/newlines
1046
+ // displayValue = String(displayValue);
1047
+ // // WhatsApp formatting:
1048
+ // // - Field label on its own line
1049
+ // // - Value on next line wrapped in backticks
1050
+ // // - Double newline between fields for readability
1051
+ // return `${field.label || field.name}\n\`${displayValue}\``;
1052
+ // });
1053
+ // // Join with double newline for spacing
1054
+ // message += fieldLines.join('\n\n');
1055
+ // // Add footer if provided
1056
+ // if (footer) {
1057
+ // message += `\n\n${footer}`;
1058
+ // }
1059
+ // return encodeURIComponent(message);
1060
+ // };
1061
+ // // Main Form Component - FIXED
1062
+ // const Form: React.FC<FormProps> = (props) => {
1063
+ // const {
1064
+ // fields: fieldsProp,
1065
+ // onSubmit: onSubmitProp,
1066
+ // defaultValues: defaultValuesProp = {},
1067
+ // submitText: submitTextProp = 'Submit',
1068
+ // submitBg: submitBgProp = 'primary',
1069
+ // submitPrefix: submitPrefixProp,
1070
+ // submitSuffix: submitSuffixProp,
1071
+ // resetText: resetTextProp = 'Reset',
1072
+ // showReset: showResetProp = true,
1073
+ // isLoading: isLoadingProp = false,
1074
+ // className: classNameProp = '',
1075
+ // layout: layoutProp = 'vertical',
1076
+ // gap: gapProp = '1.5rem',
1077
+ // title: titleProp,
1078
+ // titleSize: titleSizeProp,
1079
+ // titleColor: titleColorProp,
1080
+ // description: descriptionProp,
1081
+ // descriptionSize: descriptionSizeProp,
1082
+ // descriptionColor: descriptionColorProp,
1083
+ // whatsappContact: whatsappContactProp,
1084
+ // width: widthProp,
1085
+ // centered: centeredProp,
1086
+ // whatsappHeader: whatsappHeaderProp,
1087
+ // whatsappFooter: whatsappFooterProp,
1088
+ // fullWidth: fullWidthProp = true,
1089
+ // variant = '',
1090
+ // } = props;
1091
+ // // Use component configuration with variant
1092
+ // const { mergeWithLocal } = useComponentConfiguration('Form', variant);
1093
+ // // Create local props object
1094
+ // const localProps = {
1095
+ // fields: fieldsProp,
1096
+ // onSubmit: onSubmitProp,
1097
+ // defaultValues: defaultValuesProp,
1098
+ // submitText: submitTextProp,
1099
+ // submitBg: submitBgProp,
1100
+ // submitPrefix: submitPrefixProp,
1101
+ // submitSuffix: submitSuffixProp,
1102
+ // resetText: resetTextProp,
1103
+ // showReset: showResetProp,
1104
+ // isLoading: isLoadingProp,
1105
+ // className: classNameProp,
1106
+ // layout: layoutProp,
1107
+ // gap: gapProp,
1108
+ // title: titleProp,
1109
+ // titleSize: titleSizeProp,
1110
+ // titleColor: titleColorProp,
1111
+ // description: descriptionProp,
1112
+ // descriptionSize: descriptionSizeProp,
1113
+ // descriptionColor: descriptionColorProp,
1114
+ // whatsappContact: whatsappContactProp,
1115
+ // width: widthProp,
1116
+ // centered: centeredProp,
1117
+ // whatsappHeader: whatsappHeaderProp,
1118
+ // whatsappFooter: whatsappFooterProp,
1119
+ // fullWidth: fullWidthProp,
1120
+ // variant,
1121
+ // };
1122
+ // // Merge with theme configuration
1123
+ // const { props: mergedProps } = mergeWithLocal(localProps);
1124
+ // // Destructure with proper priority: local props override config props
1125
+ // const fields = fieldsProp !== undefined ? fieldsProp : mergedProps.fields;
1126
+ // const onSubmit = onSubmitProp !== undefined ? onSubmitProp : mergedProps.onSubmit;
1127
+ // const defaultValues = defaultValuesProp !== undefined ? defaultValuesProp : mergedProps.defaultValues;
1128
+ // const submitText = submitTextProp !== undefined ? submitTextProp : mergedProps.submitText;
1129
+ // const submitBg = submitBgProp !== undefined ? submitBgProp : mergedProps.submitBg;
1130
+ // const submitPrefix = submitPrefixProp !== undefined ? submitPrefixProp : mergedProps.submitPrefix;
1131
+ // const submitSuffix = submitSuffixProp !== undefined ? submitSuffixProp : mergedProps.submitSuffix;
1132
+ // const resetText = resetTextProp !== undefined ? resetTextProp : mergedProps.resetText;
1133
+ // const showReset = showResetProp !== undefined ? showResetProp : mergedProps.showReset;
1134
+ // const isLoading = isLoadingProp !== undefined ? isLoadingProp : mergedProps.isLoading;
1135
+ // const className = classNameProp !== undefined ? classNameProp : mergedProps.className;
1136
+ // const layout = layoutProp !== undefined ? layoutProp : mergedProps.layout;
1137
+ // const gap = gapProp !== undefined ? gapProp : mergedProps.gap;
1138
+ // const title = titleProp !== undefined ? titleProp : mergedProps.title;
1139
+ // const titleSize = titleSizeProp !== undefined ? titleSizeProp : mergedProps.titleSize;
1140
+ // const titleColor = titleColorProp !== undefined ? titleColorProp : mergedProps.titleColor;
1141
+ // const description = descriptionProp !== undefined ? descriptionProp : mergedProps.description;
1142
+ // const descriptionSize = descriptionSizeProp !== undefined ? descriptionSizeProp : mergedProps.descriptionSize;
1143
+ // const descriptionColor = descriptionColorProp !== undefined ? descriptionColorProp : mergedProps.descriptionColor;
1144
+ // const whatsappContact = whatsappContactProp !== undefined ? whatsappContactProp : mergedProps.whatsappContact;
1145
+ // const width = widthProp !== undefined ? widthProp : mergedProps.width;
1146
+ // const centered = centeredProp !== undefined ? centeredProp : mergedProps.centered;
1147
+ // const whatsappHeader = whatsappHeaderProp !== undefined ? whatsappHeaderProp : mergedProps.whatsappHeader;
1148
+ // const whatsappFooter = whatsappFooterProp !== undefined ? whatsappFooterProp : mergedProps.whatsappFooter;
1149
+ // const fullWidth = fullWidthProp !== undefined ? fullWidthProp : mergedProps.fullWidth;
1150
+ // // Parse JSON inputs
1151
+ // const parsedFields = useMemo(() => parseJsonInput(fields, [] as FormField[]), [fields]);
1152
+ // const parsedDefaultValues = useMemo(() => parseJsonInput(defaultValues, {} as Record<string, any>), [defaultValues]);
1153
+ // // State management
1154
+ // const [errors, setErrors] = useState<Record<string, string>>({});
1155
+ // const [touched, setTouched] = useState<Record<string, boolean>>({});
1156
+ // const [formValues, setFormValues] = useState<Record<string, any>>(() => {
1157
+ // // Initialize form values from defaultValues and field values
1158
+ // const initialValues: Record<string, any> = {};
1159
+ // parsedFields.forEach((field: any) => {
1160
+ // if (field.value !== undefined) {
1161
+ // initialValues[field.name] = field.value;
1162
+ // } else if (parsedDefaultValues[field.name] !== undefined) {
1163
+ // initialValues[field.name] = parsedDefaultValues[field.name];
1164
+ // } else {
1165
+ // // Set default empty values
1166
+ // if (field.type === 'checkbox' && field.multiple) {
1167
+ // initialValues[field.name] = [];
1168
+ // } else if (field.type === 'checkbox') {
1169
+ // initialValues[field.name] = false;
1170
+ // } else {
1171
+ // initialValues[field.name] = '';
1172
+ // }
1173
+ // }
1174
+ // });
1175
+ // return initialValues;
1176
+ // });
1177
+ // const [isSubmitting, setIsSubmitting] = useState(false);
1178
+ // // Update form values when defaultValues prop changes
1179
+ // useEffect(() => {
1180
+ // if (Object.keys(parsedDefaultValues).length > 0) {
1181
+ // setFormValues(prev => ({
1182
+ // ...prev,
1183
+ // ...parsedDefaultValues
1184
+ // }));
1185
+ // }
1186
+ // }, [parsedDefaultValues]);
1187
+ // // Validate a single field
1188
+ // const validateField = useCallback((field: FormField, value: any): string | null => {
1189
+ // // Required validation
1190
+ // if (field.required) {
1191
+ // if (value === undefined || value === null || value === '') {
1192
+ // return `${field.label || field.name} is required`;
1193
+ // }
1194
+ // if (field.type === 'checkbox' && field.multiple && Array.isArray(value) && value.length === 0) {
1195
+ // return `${field.label || field.name} is required`;
1196
+ // }
1197
+ // if (field.type === 'checkbox' && !field.multiple && value === false) {
1198
+ // return `${field.label || field.name} is required`;
1199
+ // }
1200
+ // }
1201
+ // // Type-specific validations (only for non-empty values)
1202
+ // if (value && (typeof value !== 'string' || value !== '')) {
1203
+ // // Email validation
1204
+ // if (field.type === 'email' && typeof value === 'string') {
1205
+ // const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1206
+ // if (!emailRegex.test(value)) {
1207
+ // return 'Please enter a valid email address';
1208
+ // }
1209
+ // }
1210
+ // // Number validation
1211
+ // if (field.type === 'number') {
1212
+ // let numValue: number;
1213
+ // if (typeof value === 'string') {
1214
+ // numValue = parseFloat(value);
1215
+ // } else if (typeof value === 'number') {
1216
+ // numValue = value;
1217
+ // } else {
1218
+ // return 'Please enter a valid number';
1219
+ // }
1220
+ // if (isNaN(numValue)) {
1221
+ // return 'Please enter a valid number';
1222
+ // }
1223
+ // const min = field.inputProps?.min;
1224
+ // const max = field.inputProps?.max;
1225
+ // if (min !== undefined && numValue < parseFloat(min.toString())) {
1226
+ // return `Minimum value is ${min}`;
1227
+ // }
1228
+ // if (max !== undefined && numValue > parseFloat(max.toString())) {
1229
+ // return `Maximum value is ${max}`;
1230
+ // }
1231
+ // }
1232
+ // // Phone validation (basic) - only for strings
1233
+ // if (field.type === 'tel' && typeof value === 'string') {
1234
+ // const phoneRegex = /^[\+]?[1-9][\d]{0,17}$/;
1235
+ // if (!phoneRegex.test(value.replace(/[\s+\-()]/g, ''))) {
1236
+ // return 'Please enter a valid phone number';
1237
+ // }
1238
+ // }
1239
+ // // Length validation for strings
1240
+ // if (typeof value === 'string') {
1241
+ // const minLength = field.inputProps?.minLength;
1242
+ // const maxLength = field.inputProps?.maxLength;
1243
+ // if (minLength && value.length < minLength) {
1244
+ // return `Minimum ${minLength} characters required`;
1245
+ // }
1246
+ // if (maxLength && value.length > maxLength) {
1247
+ // return `Maximum ${maxLength} characters allowed`;
1248
+ // }
1249
+ // }
1250
+ // // Pattern validation if provided - only for strings
1251
+ // if (field.inputProps?.pattern && typeof value === 'string') {
1252
+ // try {
1253
+ // const regex = new RegExp(field.inputProps.pattern);
1254
+ // if (!regex.test(value)) {
1255
+ // return 'Invalid format';
1256
+ // }
1257
+ // } catch (error) {
1258
+ // console.warn('Invalid regex pattern:', field.inputProps.pattern);
1259
+ // }
1260
+ // }
1261
+ // }
1262
+ // return null;
1263
+ // }, []);
1264
+ // // Validate form
1265
+ // const validateForm = useCallback((): boolean => {
1266
+ // const newErrors: Record<string, string> = {};
1267
+ // let hasErrors = false;
1268
+ // parsedFields.forEach((field: any) => {
1269
+ // const value = formValues[field.name];
1270
+ // const error = validateField(field, value);
1271
+ // if (error) {
1272
+ // newErrors[field.name] = error;
1273
+ // hasErrors = true;
1274
+ // }
1275
+ // });
1276
+ // setErrors(newErrors);
1277
+ // return !hasErrors;
1278
+ // }, [parsedFields, validateField, formValues]);
1279
+ // // Handle field change for checkboxes and radios
1280
+ // const handleFieldChange = useCallback((fieldName: string, newValue: any) => {
1281
+ // // Update form values
1282
+ // setFormValues(prev => ({
1283
+ // ...prev,
1284
+ // [fieldName]: newValue
1285
+ // }));
1286
+ // // Update touched state
1287
+ // setTouched(prev => ({ ...prev, [fieldName]: true }));
1288
+ // // Validate the changed field
1289
+ // const field = parsedFields.find((f: any) => f.name === fieldName);
1290
+ // if (!field) return;
1291
+ // const error = validateField(field, newValue);
1292
+ // setErrors(prev => {
1293
+ // if (error) {
1294
+ // return { ...prev, [fieldName]: error };
1295
+ // } else {
1296
+ // const newErrors = { ...prev };
1297
+ // delete newErrors[fieldName];
1298
+ // return newErrors;
1299
+ // }
1300
+ // });
1301
+ // }, [parsedFields, validateField]);
1302
+ // // FIXED: Handle input change - pass event directly to Input component
1303
+ // const handleInputEventChange = useCallback((e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
1304
+ // const fieldName = e.target.name;
1305
+ // const value = e.target.value;
1306
+ // // Update form values - PASS VALUE AS-IS (preserves spaces)
1307
+ // setFormValues(prev => ({
1308
+ // ...prev,
1309
+ // [fieldName]: value
1310
+ // }));
1311
+ // // Update touched state
1312
+ // setTouched(prev => ({ ...prev, [fieldName]: true }));
1313
+ // // Validate the changed field
1314
+ // const field = parsedFields.find((f: any) => f.name === fieldName);
1315
+ // if (!field) return;
1316
+ // const error = validateField(field, value);
1317
+ // setErrors(prev => {
1318
+ // if (error) {
1319
+ // return { ...prev, [fieldName]: error };
1320
+ // } else {
1321
+ // const newErrors = { ...prev };
1322
+ // delete newErrors[fieldName];
1323
+ // return newErrors;
1324
+ // }
1325
+ // });
1326
+ // }, [parsedFields, validateField]);
1327
+ // // FIXED: Handle blur event - pass event directly to Input component
1328
+ // const handleInputEventBlur = useCallback((e: React.FocusEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
1329
+ // const fieldName = e.target.name;
1330
+ // setTouched(prev => ({ ...prev, [fieldName]: true }));
1331
+ // // Validate the field
1332
+ // const field = parsedFields.find((f: any) => f.name === fieldName);
1333
+ // if (!field) return;
1334
+ // const value = formValues[fieldName];
1335
+ // const error = validateField(field, value);
1336
+ // setErrors(prev => {
1337
+ // if (error) {
1338
+ // return { ...prev, [fieldName]: error };
1339
+ // } else {
1340
+ // const newErrors = { ...prev };
1341
+ // delete newErrors[fieldName];
1342
+ // return newErrors;
1343
+ // }
1344
+ // });
1345
+ // }, [parsedFields, validateField, formValues]);
1346
+ // // Handle form submission
1347
+ // const handleSubmit = useCallback(async (e: React.FormEvent) => {
1348
+ // e.preventDefault();
1349
+ // // Mark all fields as touched
1350
+ // const allTouched: Record<string, boolean> = {};
1351
+ // parsedFields.forEach((field: any) => {
1352
+ // allTouched[field.name] = true;
1353
+ // });
1354
+ // setTouched(allTouched);
1355
+ // // Validate form
1356
+ // const isValid = validateForm();
1357
+ // if (!isValid) {
1358
+ // // Scroll to first error
1359
+ // const firstErrorField = Object.keys(errors)[0];
1360
+ // if (firstErrorField) {
1361
+ // const element = document.getElementById(`form-field-${firstErrorField}`);
1362
+ // element?.scrollIntoView({ behavior: 'smooth', block: 'center' });
1363
+ // }
1364
+ // return;
1365
+ // }
1366
+ // // Get form data and submit
1367
+ // setIsSubmitting(true);
1368
+ // try {
1369
+ // if (whatsappContact) {
1370
+ // // Submit via WhatsApp
1371
+ // const message = formatWhatsAppMessage(formValues, parsedFields, whatsappHeader, whatsappFooter);
1372
+ // const cleanPhone = whatsappContact.replace(/[\s+\-()]/g, '');
1373
+ // const whatsappUrl = `https://wa.me/${cleanPhone}?text=${message}`;
1374
+ // window.open(whatsappUrl, '_blank');
1375
+ // // Still call onSubmit if provided
1376
+ // if (onSubmit) {
1377
+ // await onSubmit(formValues, true);
1378
+ // }
1379
+ // } else {
1380
+ // // Regular submission
1381
+ // if (onSubmit) {
1382
+ // await onSubmit(formValues, false);
1383
+ // }
1384
+ // }
1385
+ // } catch (error) {
1386
+ // console.error('Form submission error:', error);
1387
+ // setErrors(prev => ({
1388
+ // ...prev,
1389
+ // _form: 'There was an error submitting the form. Please try again.'
1390
+ // }));
1391
+ // } finally {
1392
+ // setIsSubmitting(false);
1393
+ // }
1394
+ // }, [parsedFields, validateForm, formValues, whatsappContact, whatsappHeader, whatsappFooter, onSubmit, errors]);
1395
+ // // Handle form reset
1396
+ // const handleReset = useCallback(() => {
1397
+ // // Reset to initial values
1398
+ // const initialValues: Record<string, any> = {};
1399
+ // parsedFields.forEach((field: any) => {
1400
+ // if (field.value !== undefined) {
1401
+ // initialValues[field.name] = field.value;
1402
+ // } else if (parsedDefaultValues[field.name] !== undefined) {
1403
+ // initialValues[field.name] = parsedDefaultValues[field.name];
1404
+ // } else {
1405
+ // if (field.type === 'checkbox' && field.multiple) {
1406
+ // initialValues[field.name] = [];
1407
+ // } else if (field.type === 'checkbox') {
1408
+ // initialValues[field.name] = false;
1409
+ // } else {
1410
+ // initialValues[field.name] = '';
1411
+ // }
1412
+ // }
1413
+ // });
1414
+ // setFormValues(initialValues);
1415
+ // setErrors({});
1416
+ // setTouched({});
1417
+ // }, [parsedFields, parsedDefaultValues]);
1418
+ // // Get field status for Input component
1419
+ // const getFieldStatus = useCallback((fieldName: string): 'success' | 'warning' | 'danger' | 'info' | undefined => {
1420
+ // const error = errors[fieldName];
1421
+ // const isTouched = touched[fieldName];
1422
+ // if (error) return 'danger';
1423
+ // if (isTouched && !error && formValues[fieldName] !== '') {
1424
+ // return 'success';
1425
+ // }
1426
+ // return undefined;
1427
+ // }, [errors, touched, formValues]);
1428
+ // // Check if form is valid for submission
1429
+ // const isFormValid = useMemo(() => {
1430
+ // // Check if any required fields are empty
1431
+ // const hasEmptyRequiredFields = parsedFields.some((field: any) => {
1432
+ // if (!field.required) return false;
1433
+ // const value = formValues[field.name];
1434
+ // if (field.type === 'checkbox' && field.multiple) {
1435
+ // return !Array.isArray(value) || value.length === 0;
1436
+ // }
1437
+ // if (field.type === 'checkbox') {
1438
+ // return value === false;
1439
+ // }
1440
+ // return !value || value === '';
1441
+ // });
1442
+ // // Check if there are any validation errors
1443
+ // const hasValidationErrors = Object.keys(errors).length > 0;
1444
+ // return !hasEmptyRequiredFields && !hasValidationErrors;
1445
+ // }, [parsedFields, formValues, errors]);
1446
+ // // Submit button disabled state
1447
+ // const isSubmitDisabled = isSubmitting || isLoading || !isFormValid;
1448
+ // // Check if WhatsApp is configured
1449
+ // const hasWhatsApp = !!whatsappContact;
1450
+ // // Render field based on type - FIXED
1451
+ // const renderField = useCallback((field: FormField) => {
1452
+ // const status = getFieldStatus(field.name);
1453
+ // const error = errors[field.name];
1454
+ // const isTouched = touched[field.name];
1455
+ // const showError = error && isTouched;
1456
+ // const value = formValues[field.name];
1457
+ // // Field wrapper classes
1458
+ // const wrapperClass = `col min-w-200 field ${showError ? 'field-error' : ''}`.trim();
1459
+ // // Helper text (error takes priority)
1460
+ // const helperText = showError ? error : field.helperText;
1461
+ // // Generate unique ID for the input
1462
+ // const inputId = field.inputProps?.id || `form-field-${field.name}`;
1463
+ // // Base props for Input component
1464
+ // const baseProps: any = {
1465
+ // id: inputId,
1466
+ // name: field.name, // IMPORTANT: Make sure name is passed
1467
+ // label: field.label,
1468
+ // placeholder: field.placeholder,
1469
+ // helperText: helperText,
1470
+ // disabled: field.disabled || isLoading,
1471
+ // fullWidth: fullWidth,
1472
+ // ...field.inputProps,
1473
+ // };
1474
+ // // Only add status if it's not undefined
1475
+ // if (status !== undefined) {
1476
+ // baseProps.status = status;
1477
+ // }
1478
+ // // Render based on field type
1479
+ // switch (field.type) {
1480
+ // case 'checkbox':
1481
+ // if (field.options?.length) {
1482
+ // // Multiple checkboxes (checkbox group)
1483
+ // const checkedValues = Array.isArray(value) ? value : [];
1484
+ // return (
1485
+ // <div key={field.name} className={wrapperClass}>
1486
+ // {field.label && (
1487
+ // <div className="form-label" style={{ marginBottom: '0.5rem' }}>
1488
+ // <Text text={field.label + (field.required ? ' *' : '')} size="sm" color="text" bold />
1489
+ // </div>
1490
+ // )}
1491
+ // <Flex direction="column" gap="0.5rem">
1492
+ // {field.options.map((option, index) => {
1493
+ // const isChecked = checkedValues.includes(option.value);
1494
+ // return (
1495
+ // <FormCheckbox
1496
+ // key={`${field.name}_${index}`}
1497
+ // id={`${inputId}_${index}`}
1498
+ // label={option.label}
1499
+ // checked={isChecked}
1500
+ // onChange={(checked) => {
1501
+ // if (checked) {
1502
+ // // Add value to array
1503
+ // const newValues = [...checkedValues, option.value];
1504
+ // handleFieldChange(field.name, newValues);
1505
+ // } else {
1506
+ // // Remove value from array
1507
+ // const newValues = checkedValues.filter(v => v !== option.value);
1508
+ // handleFieldChange(field.name, newValues);
1509
+ // }
1510
+ // }}
1511
+ // disabled={field.disabled || option.disabled || isLoading}
1512
+ // required={field.required && index === 0}
1513
+ // value={option.value}
1514
+ // />
1515
+ // );
1516
+ // })}
1517
+ // </Flex>
1518
+ // </div>
1519
+ // );
1520
+ // } else {
1521
+ // // Single checkbox (boolean)
1522
+ // return (
1523
+ // <div key={field.name} className={wrapperClass}>
1524
+ // <FormCheckbox
1525
+ // label={field.label}
1526
+ // checked={!!value}
1527
+ // onChange={(checked) => handleFieldChange(field.name, checked)}
1528
+ // disabled={field.disabled || isLoading}
1529
+ // required={field.required}
1530
+ // id={inputId}
1531
+ // />
1532
+ // </div>
1533
+ // );
1534
+ // }
1535
+ // case 'radio':
1536
+ // if (!field.options?.length) return null;
1537
+ // return (
1538
+ // <div key={field.name} className={wrapperClass}>
1539
+ // {field.label && (
1540
+ // <div className="form-label" style={{ marginBottom: '0.5rem' }}>
1541
+ // <Text text={field.label + (field.required ? ' *' : '')} size="sm" color="text" bold />
1542
+ // </div>
1543
+ // )}
1544
+ // <Flex direction="column" gap="0.5rem">
1545
+ // {field.options.map((option, index) => (
1546
+ // <FormRadio
1547
+ // key={`${field.name}_${index}`}
1548
+ // id={`${inputId}_${index}`}
1549
+ // label={option.label}
1550
+ // checked={value === option.value}
1551
+ // onChange={() => handleFieldChange(field.name, option.value)}
1552
+ // disabled={field.disabled || option.disabled || isLoading}
1553
+ // required={field.required && index === 0}
1554
+ // value={option.value}
1555
+ // />
1556
+ // ))}
1557
+ // </Flex>
1558
+ // </div>
1559
+ // );
1560
+ // case 'textarea':
1561
+ // return (
1562
+ // <div key={field.name} className={wrapperClass}>
1563
+ // <Input
1564
+ // multiline
1565
+ // rows={field.inputProps?.rows || 4}
1566
+ // value={value || ''}
1567
+ // onChange={handleInputEventChange} // FIXED: Pass event handler directly
1568
+ // onBlur={handleInputEventBlur} // FIXED: Pass event handler directly
1569
+ // {...baseProps}
1570
+ // />
1571
+ // </div>
1572
+ // );
1573
+ // case 'select':
1574
+ // return (
1575
+ // <div key={field.name} className={wrapperClass}>
1576
+ // <Input
1577
+ // select
1578
+ // options={field.options?.map(opt => ({ text: opt.label, value: opt.value })) || []}
1579
+ // value={value || ''}
1580
+ // onChange={handleInputEventChange} // FIXED: Pass event handler directly
1581
+ // onBlur={handleInputEventBlur} // FIXED: Pass event handler directly
1582
+ // {...baseProps}
1583
+ // />
1584
+ // </div>
1585
+ // );
1586
+ // default:
1587
+ // // text, email, number, tel, date, file, password
1588
+ // return (
1589
+ // <div key={field.name} className={wrapperClass}>
1590
+ // <Input
1591
+ // type={field.type}
1592
+ // value={value || ''}
1593
+ // onChange={handleInputEventChange} // FIXED: Pass event handler directly
1594
+ // onBlur={handleInputEventBlur} // FIXED: Pass event handler directly
1595
+ // {...baseProps}
1596
+ // />
1597
+ // </div>
1598
+ // );
1599
+ // }
1600
+ // }, [errors, touched, formValues, isLoading, getFieldStatus, handleFieldChange, handleInputEventChange, handleInputEventBlur, fullWidth]);
1601
+ // // Don't render if no fields are configured
1602
+ // if (parsedFields.length === 0) {
1603
+ // console.warn('Form: No fields configured. Please provide fields prop or configure via theme.');
1604
+ // return null;
1605
+ // }
1606
+ // return (
1607
+ // <div className={`form-wrapper ${centered ? 'center' : ''} ${className}`} style={{ width: "100%", maxWidth: width || "450px" }}>
1608
+ // {/* Title Section */}
1609
+ // {title && (
1610
+ // <div className="form-header" style={{ marginBottom: '2rem' }}>
1611
+ // <Text
1612
+ // text={title}
1613
+ // size={titleSize || "3xl"}
1614
+ // color={titleColor || ""}
1615
+ // block
1616
+ // />
1617
+ // {description && (
1618
+ // <Text article
1619
+ // size={descriptionSize || "sm"}
1620
+ // color={descriptionColor || ""}
1621
+ // >
1622
+ // <div
1623
+ // className="article text-sm"
1624
+ // dangerouslySetInnerHTML={{ __html: description }}
1625
+ // />
1626
+ // </Text>
1627
+ // )}
1628
+ // </div>
1629
+ // )}
1630
+ // <form
1631
+ // className="form"
1632
+ // onSubmit={handleSubmit}
1633
+ // style={{ width: '100%' }}
1634
+ // >
1635
+ // {/* Form fields wrapped in Flex */}
1636
+ // <Flex
1637
+ // direction={layout === 'horizontal' ? 'row' : 'column'}
1638
+ // gap={gap}
1639
+ // width='100%'
1640
+ // >
1641
+ // {parsedFields.map(renderField)}
1642
+ // </Flex>
1643
+ // {/* Form actions - SINGLE BUTTON */}
1644
+ // <Flex direction="column" gap="1rem" style={{ marginTop: '2rem', width: fullWidth ? '100%' : undefined }}>
1645
+ // {/* Single submit button */}
1646
+ // <Button
1647
+ // type="submit"
1648
+ // text={hasWhatsApp ? `Send via WhatsApp` : submitText}
1649
+ // bg={submitBg || "primary"}
1650
+ // raised
1651
+ // prefix={submitPrefix || hasWhatsApp ? <PiWhatsappLogo /> : <PiPaperPlaneTilt />}
1652
+ // suffix={submitSuffix}
1653
+ // disabled={isSubmitDisabled}
1654
+ // isLoading={isSubmitting || isLoading}
1655
+ // fullWidth={fullWidth}
1656
+ // />
1657
+ // </Flex>
1658
+ // </form>
1659
+ // </div>
1660
+ // );
1661
+ // };
1662
+ // export default Form;