funuicss 3.8.11 → 3.8.13

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
@@ -164,7 +164,7 @@ var FormCheckbox = function (_a) {
164
164
  alignItems: 'center',
165
165
  justifyContent: 'center',
166
166
  flexShrink: 0,
167
- } }, checked && (react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", style: {
167
+ } }, checked && (react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org2000/svg", style: {
168
168
  stroke: 'white',
169
169
  strokeWidth: '2',
170
170
  strokeLinecap: 'round',
@@ -282,7 +282,7 @@ var formatWhatsAppMessage = function (values, fields, header, footer) {
282
282
  }
283
283
  return encodeURIComponent(message);
284
284
  };
285
- // Main Form Component - MODIFIED for submit-only validation
285
+ // Main Form Component - FIXED
286
286
  var Form = function (props) {
287
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;
288
288
  // Use component configuration with variant
@@ -349,7 +349,8 @@ var Form = function (props) {
349
349
  var parsedDefaultValues = (0, react_1.useMemo)(function () { return parseJsonInput(defaultValues, {}); }, [defaultValues]);
350
350
  // State management
351
351
  var _m = (0, react_1.useState)({}), errors = _m[0], setErrors = _m[1];
352
- var _o = (0, react_1.useState)(function () {
352
+ var _o = (0, react_1.useState)({}), touched = _o[0], setTouched = _o[1];
353
+ var _p = (0, react_1.useState)(function () {
353
354
  // Initialize form values from defaultValues and field values
354
355
  var initialValues = {};
355
356
  parsedFields.forEach(function (field) {
@@ -373,9 +374,8 @@ var Form = function (props) {
373
374
  }
374
375
  });
375
376
  return initialValues;
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];
377
+ }), formValues = _p[0], setFormValues = _p[1];
378
+ var _q = (0, react_1.useState)(false), isSubmitting = _q[0], setIsSubmitting = _q[1];
379
379
  // Update form values when defaultValues prop changes
380
380
  (0, react_1.useEffect)(function () {
381
381
  if (Object.keys(parsedDefaultValues).length > 0) {
@@ -476,7 +476,6 @@ var Form = function (props) {
476
476
  }
477
477
  });
478
478
  setErrors(newErrors);
479
- setHasBeenSubmitted(true);
480
479
  return !hasErrors;
481
480
  }, [parsedFields, validateField, formValues]);
482
481
  // Handle field change for checkboxes and radios
@@ -486,36 +485,96 @@ var Form = function (props) {
486
485
  var _a;
487
486
  return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = newValue, _a)));
488
487
  });
489
- // Clear error for this field when user makes a change
488
+ // Update touched state
489
+ setTouched(function (prev) {
490
+ var _a;
491
+ return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
492
+ });
493
+ // Validate the changed field
494
+ var field = parsedFields.find(function (f) { return f.name === fieldName; });
495
+ if (!field)
496
+ return;
497
+ var error = validateField(field, newValue);
490
498
  setErrors(function (prev) {
491
- var newErrors = __assign({}, prev);
492
- delete newErrors[fieldName];
493
- return newErrors;
499
+ var _a;
500
+ if (error) {
501
+ return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
502
+ }
503
+ else {
504
+ var newErrors = __assign({}, prev);
505
+ delete newErrors[fieldName];
506
+ return newErrors;
507
+ }
494
508
  });
495
- }, []);
496
- // Handle input change - NO VALIDATION ON CHANGE
509
+ }, [parsedFields, validateField]);
510
+ // FIXED: Handle input change - pass event directly to Input component
497
511
  var handleInputEventChange = (0, react_1.useCallback)(function (e) {
498
512
  var fieldName = e.target.name;
499
513
  var value = e.target.value;
500
- // Update form values
514
+ // Update form values - PASS VALUE AS-IS (preserves spaces)
501
515
  setFormValues(function (prev) {
502
516
  var _a;
503
517
  return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = value, _a)));
504
518
  });
505
- // Clear error for this field when user makes a change
519
+ // Update touched state
520
+ setTouched(function (prev) {
521
+ var _a;
522
+ return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
523
+ });
524
+ // Validate the changed field
525
+ var field = parsedFields.find(function (f) { return f.name === fieldName; });
526
+ if (!field)
527
+ return;
528
+ var error = validateField(field, value);
506
529
  setErrors(function (prev) {
507
- var newErrors = __assign({}, prev);
508
- delete newErrors[fieldName];
509
- return newErrors;
530
+ var _a;
531
+ if (error) {
532
+ return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
533
+ }
534
+ else {
535
+ var newErrors = __assign({}, prev);
536
+ delete newErrors[fieldName];
537
+ return newErrors;
538
+ }
510
539
  });
511
- }, []);
540
+ }, [parsedFields, validateField]);
541
+ // FIXED: Handle blur event - pass event directly to Input component
542
+ var handleInputEventBlur = (0, react_1.useCallback)(function (e) {
543
+ var fieldName = e.target.name;
544
+ setTouched(function (prev) {
545
+ var _a;
546
+ return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
547
+ });
548
+ // Validate the field
549
+ var field = parsedFields.find(function (f) { return f.name === fieldName; });
550
+ if (!field)
551
+ return;
552
+ var value = formValues[fieldName];
553
+ var error = validateField(field, value);
554
+ setErrors(function (prev) {
555
+ var _a;
556
+ if (error) {
557
+ return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
558
+ }
559
+ else {
560
+ var newErrors = __assign({}, prev);
561
+ delete newErrors[fieldName];
562
+ return newErrors;
563
+ }
564
+ });
565
+ }, [parsedFields, validateField, formValues]);
512
566
  // Handle form submission
513
567
  var handleSubmit = (0, react_1.useCallback)(function (e) { return __awaiter(void 0, void 0, void 0, function () {
514
- var isValid, firstErrorField, element, message, cleanPhone, whatsappUrl, error_1;
568
+ var allTouched, isValid, firstErrorField, element, message, cleanPhone, whatsappUrl, error_1;
515
569
  return __generator(this, function (_a) {
516
570
  switch (_a.label) {
517
571
  case 0:
518
572
  e.preventDefault();
573
+ allTouched = {};
574
+ parsedFields.forEach(function (field) {
575
+ allTouched[field.name] = true;
576
+ });
577
+ setTouched(allTouched);
519
578
  isValid = validateForm();
520
579
  if (!isValid) {
521
580
  firstErrorField = Object.keys(errors)[0];
@@ -559,7 +618,7 @@ var Form = function (props) {
559
618
  case 9: return [2 /*return*/];
560
619
  }
561
620
  });
562
- }); }, [validateForm, formValues, whatsappContact, whatsappHeader, whatsappFooter, onSubmit, errors, parsedFields]);
621
+ }); }, [parsedFields, validateForm, formValues, whatsappContact, whatsappHeader, whatsappFooter, onSubmit, errors]);
563
622
  // Handle form reset
564
623
  var handleReset = (0, react_1.useCallback)(function () {
565
624
  // Reset to initial values
@@ -585,36 +644,49 @@ var Form = function (props) {
585
644
  });
586
645
  setFormValues(initialValues);
587
646
  setErrors({});
588
- setHasBeenSubmitted(false);
647
+ setTouched({});
589
648
  }, [parsedFields, parsedDefaultValues]);
590
649
  // Get field status for Input component
591
650
  var getFieldStatus = (0, react_1.useCallback)(function (fieldName) {
592
651
  var error = errors[fieldName];
593
- // Only show validation status if form has been submitted and there's an error
594
- if (hasBeenSubmitted && error) {
652
+ var isTouched = touched[fieldName];
653
+ if (error)
595
654
  return 'danger';
655
+ if (isTouched && !error && formValues[fieldName] !== '') {
656
+ return 'success';
596
657
  }
597
658
  return undefined;
598
- }, [errors, hasBeenSubmitted]);
659
+ }, [errors, touched, formValues]);
599
660
  // Check if form is valid for submission
600
661
  var isFormValid = (0, react_1.useMemo)(function () {
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]);
662
+ // Check if any required fields are empty
663
+ var hasEmptyRequiredFields = parsedFields.some(function (field) {
664
+ if (!field.required)
665
+ return false;
666
+ var value = formValues[field.name];
667
+ if (field.type === 'checkbox' && field.multiple) {
668
+ return !Array.isArray(value) || value.length === 0;
669
+ }
670
+ if (field.type === 'checkbox') {
671
+ return value === false;
672
+ }
673
+ return !value || value === '';
674
+ });
675
+ // Check if there are any validation errors
676
+ var hasValidationErrors = Object.keys(errors).length > 0;
677
+ return !hasEmptyRequiredFields && !hasValidationErrors;
678
+ }, [parsedFields, formValues, errors]);
608
679
  // Submit button disabled state
609
- var isSubmitDisabled = isSubmitting || isLoading;
680
+ var isSubmitDisabled = isSubmitting || isLoading || !isFormValid;
610
681
  // Check if WhatsApp is configured
611
682
  var hasWhatsApp = !!whatsappContact;
612
- // Render field based on type
683
+ // Render field based on type - FIXED
613
684
  var renderField = (0, react_1.useCallback)(function (field) {
614
685
  var _a, _b, _c, _d, _e;
615
686
  var status = getFieldStatus(field.name);
616
687
  var error = errors[field.name];
617
- var showError = hasBeenSubmitted && error;
688
+ var isTouched = touched[field.name];
689
+ var showError = error && isTouched;
618
690
  var value = formValues[field.name];
619
691
  // Field wrapper classes
620
692
  var wrapperClass = "col min-w-200 field ".concat(showError ? 'field-error' : '').trim();
@@ -667,16 +739,16 @@ var Form = function (props) {
667
739
  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 })); }))));
668
740
  case 'textarea':
669
741
  return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
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))));
742
+ 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, onBlur: handleInputEventBlur }, baseProps))));
671
743
  case 'select':
672
744
  return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
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))));
745
+ 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, onBlur: handleInputEventBlur }, baseProps))));
674
746
  default:
675
747
  // text, email, number, tel, date, file, password
676
748
  return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
677
- react_1.default.createElement(Input_1.default, __assign({ type: field.type, value: value || '', onChange: handleInputEventChange }, baseProps))));
749
+ react_1.default.createElement(Input_1.default, __assign({ type: field.type, value: value || '', onChange: handleInputEventChange, onBlur: handleInputEventBlur }, baseProps))));
678
750
  }
679
- }, [errors, hasBeenSubmitted, formValues, isLoading, getFieldStatus, handleFieldChange, handleInputEventChange, fullWidth]);
751
+ }, [errors, touched, formValues, isLoading, getFieldStatus, handleFieldChange, handleInputEventChange, handleInputEventBlur, fullWidth]);
680
752
  // Don't render if no fields are configured
681
753
  if (parsedFields.length === 0) {
682
754
  console.warn('Form: No fields configured. Please provide fields prop or configure via theme.');
@@ -693,970 +765,3 @@ var Form = function (props) {
693
765
  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 })))));
694
766
  };
695
767
  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;