@sikka/aps 0.0.1 → 0.0.2

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.
@@ -456,23 +456,50 @@ var defaultStyles = {
456
456
  borderRadius: "8px",
457
457
  fontSize: "13px",
458
458
  color: "#065F46"
459
+ },
460
+ errorMessage: {
461
+ color: "#EF4444",
462
+ fontSize: "12px"
463
+ },
464
+ helperText: {
465
+ fontSize: "12px",
466
+ color: "#6B7280"
459
467
  }
460
468
  };
469
+ var defaultFieldConfig = {
470
+ cardNumber: { visible: true, required: true },
471
+ cardHolder: { visible: true, required: true },
472
+ customerEmail: { visible: true, required: false },
473
+ expiryDate: { visible: true, required: true },
474
+ cvv: { visible: true, required: true }
475
+ };
461
476
  var TokenizationForm = ({
462
477
  actionUrl,
463
478
  formParams,
464
479
  customerEmail = "",
465
480
  onSuccess: _onSuccess,
466
- // Success is handled via returnUrl redirect
467
481
  onError,
468
482
  styles = {},
469
483
  icons = {},
484
+ fields = {},
485
+ layout = { type: "vertical" },
470
486
  labels = {},
471
487
  placeholders = {},
472
488
  disableFormatting = false,
473
489
  showCardIcons = true,
474
490
  showSecurityNotice = true,
475
- className = {}
491
+ securityNotice,
492
+ submitButton,
493
+ className = {},
494
+ errorMessages = {},
495
+ fieldOrder = ["cardNumber", "cardHolder", "customerEmail", "expiryDate", "cvv"],
496
+ beforeForm,
497
+ afterForm,
498
+ beforeSubmit,
499
+ afterSubmit,
500
+ nativeSubmission = true,
501
+ onChange,
502
+ onValidSubmit
476
503
  }) => {
477
504
  const [cardNumber, setCardNumber] = (0, import_react4.useState)("");
478
505
  const [expiryDate, setExpiryDate] = (0, import_react4.useState)("");
@@ -490,6 +517,13 @@ var TokenizationForm = ({
490
517
  ...DefaultIcons,
491
518
  ...icons
492
519
  };
520
+ const mergedFields = {
521
+ cardNumber: { ...defaultFieldConfig.cardNumber, ...fields.cardNumber },
522
+ cardHolder: { ...defaultFieldConfig.cardHolder, ...fields.cardHolder },
523
+ customerEmail: { ...defaultFieldConfig.customerEmail, ...fields.customerEmail },
524
+ expiryDate: { ...defaultFieldConfig.expiryDate, ...fields.expiryDate },
525
+ cvv: { ...defaultFieldConfig.cvv, ...fields.cvv }
526
+ };
493
527
  const mergedLabels = {
494
528
  cardNumber: "Card Number",
495
529
  cardHolder: "Card Holder Name",
@@ -508,6 +542,16 @@ var TokenizationForm = ({
508
542
  cvv: "123",
509
543
  ...placeholders
510
544
  };
545
+ const mergedErrorMessages = {
546
+ cardNumber: "Invalid card number",
547
+ cardHolder: "Card holder name is required",
548
+ customerEmail: "Invalid email address",
549
+ expiryDate: "Invalid expiry date",
550
+ cvv: "Invalid CVV",
551
+ required: "This field is required",
552
+ invalidEmail: "Invalid email address",
553
+ ...errorMessages
554
+ };
511
555
  const formatCardNumber = (value) => {
512
556
  if (disableFormatting) return value;
513
557
  const v = value.replace(/\s+/g, "").replace(/[^0-9]/gi, "");
@@ -530,24 +574,75 @@ var TokenizationForm = ({
530
574
  }
531
575
  return v;
532
576
  };
533
- const validateForm = () => {
577
+ const isValidExpiryDate = (value) => {
578
+ if (!value || value.length !== 5) return false;
579
+ const [month, year] = value.split("/");
580
+ if (!month || !year) return false;
581
+ const mm = parseInt(month, 10);
582
+ const yy = parseInt(year, 10);
583
+ if (mm < 1 || mm > 12) return false;
584
+ if (yy < 0 || yy > 99) return false;
585
+ const now = /* @__PURE__ */ new Date();
586
+ const currentYear = now.getFullYear() % 100;
587
+ const currentMonth = now.getMonth() + 1;
588
+ if (yy < currentYear) return false;
589
+ if (yy === currentYear && mm < currentMonth) return false;
590
+ return true;
591
+ };
592
+ const getFormData = () => ({
593
+ cardNumber,
594
+ cardHolderName,
595
+ email,
596
+ expiryDate,
597
+ cvv,
598
+ cardBrand,
599
+ isValid: validateForm(false)
600
+ });
601
+ const validateForm = (updateErrors = true) => {
534
602
  const newErrors = {};
535
- if (!cardNumber || cardNumber.replace(/\s/g, "").length < 13) {
536
- newErrors.cardNumber = "Invalid card number";
603
+ if (mergedFields.cardNumber?.visible && mergedFields.cardNumber?.required !== false) {
604
+ const customError = mergedFields.cardNumber?.validate?.(cardNumber);
605
+ if (customError) {
606
+ newErrors.cardNumber = customError;
607
+ } else if (!cardNumber || cardNumber.replace(/\s/g, "").length < 13) {
608
+ newErrors.cardNumber = mergedErrorMessages.cardNumber;
609
+ }
537
610
  }
538
- if (!expiryDate || expiryDate.length !== 5) {
539
- newErrors.expiryDate = "Invalid expiry date";
611
+ if (mergedFields.cardHolder?.visible && mergedFields.cardHolder?.required !== false) {
612
+ const customError = mergedFields.cardHolder?.validate?.(cardHolderName);
613
+ if (customError) {
614
+ newErrors.cardHolder = customError;
615
+ } else if (!cardHolderName || cardHolderName.length < 2) {
616
+ newErrors.cardHolder = mergedErrorMessages.cardHolder;
617
+ }
540
618
  }
541
- if (!cvv || cvv.length < 3) {
542
- newErrors.cvv = "Invalid CVV";
619
+ if (mergedFields.customerEmail?.visible && email) {
620
+ const customError = mergedFields.customerEmail?.validate?.(email);
621
+ if (customError) {
622
+ newErrors.email = customError;
623
+ } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
624
+ newErrors.email = mergedErrorMessages.customerEmail;
625
+ }
543
626
  }
544
- if (!cardHolderName || cardHolderName.length < 2) {
545
- newErrors.cardHolder = "Card holder name is required";
627
+ if (mergedFields.expiryDate?.visible && mergedFields.expiryDate?.required !== false) {
628
+ const customError = mergedFields.expiryDate?.validate?.(expiryDate);
629
+ if (customError) {
630
+ newErrors.expiryDate = customError;
631
+ } else if (!expiryDate || !isValidExpiryDate(expiryDate)) {
632
+ newErrors.expiryDate = mergedErrorMessages.expiryDate;
633
+ }
634
+ }
635
+ if (mergedFields.cvv?.visible && mergedFields.cvv?.required !== false) {
636
+ const customError = mergedFields.cvv?.validate?.(cvv);
637
+ if (customError) {
638
+ newErrors.cvv = customError;
639
+ } else if (!cvv || cvv.length < 3) {
640
+ newErrors.cvv = mergedErrorMessages.cvv;
641
+ }
546
642
  }
547
- if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
548
- newErrors.email = "Invalid email address";
643
+ if (updateErrors) {
644
+ setErrors(newErrors);
549
645
  }
550
- setErrors(newErrors);
551
646
  return Object.keys(newErrors).length === 0;
552
647
  };
553
648
  const handleSubmit = (e) => {
@@ -556,6 +651,14 @@ var TokenizationForm = ({
556
651
  onError?.("Please fill in all required fields correctly");
557
652
  return;
558
653
  }
654
+ const formData = getFormData();
655
+ if (onValidSubmit) {
656
+ onValidSubmit(formData);
657
+ return;
658
+ }
659
+ if (!nativeSubmission) {
660
+ return;
661
+ }
559
662
  setLoading(true);
560
663
  const form = document.createElement("form");
561
664
  form.method = "POST";
@@ -576,7 +679,10 @@ var TokenizationForm = ({
576
679
  form.appendChild(input);
577
680
  };
578
681
  const cleanCardNumber = cardNumber.replace(/\s/g, "");
579
- const cleanExpiryDate = expiryDate.replace("/", "");
682
+ const cleanExpiry = expiryDate.replace(/\//g, "");
683
+ const mm = cleanExpiry.substring(0, 2);
684
+ const yy = cleanExpiry.substring(2, 4);
685
+ const cleanExpiryDate = yy + mm;
580
686
  addHiddenInput("card_number", cleanCardNumber);
581
687
  addHiddenInput("expiry_date", cleanExpiryDate);
582
688
  addHiddenInput("card_security_code", cvv);
@@ -585,156 +691,342 @@ var TokenizationForm = ({
585
691
  form.submit();
586
692
  setLoading(false);
587
693
  };
588
- const handleCardNumberChange = (e) => {
589
- const formatted = formatCardNumber(e.target.value);
694
+ const handleCardNumberChange = (value) => {
695
+ const formatted = formatCardNumber(value);
590
696
  setCardNumber(formatted);
591
697
  setCardBrand(detectCardBrand(formatted));
592
698
  if (errors.cardNumber) {
593
699
  setErrors({ ...errors, cardNumber: "" });
594
700
  }
701
+ onChange?.(getFormData());
595
702
  };
596
- const handleExpiryDateChange = (e) => {
597
- const formatted = formatExpiryDate(e.target.value);
703
+ const handleExpiryDateChange = (value) => {
704
+ const formatted = formatExpiryDate(value);
598
705
  setExpiryDate(formatted);
599
706
  if (errors.expiryDate) {
600
707
  setErrors({ ...errors, expiryDate: "" });
601
708
  }
709
+ onChange?.(getFormData());
602
710
  };
603
- const handleCvvChange = (e) => {
604
- const value = e.target.value.replace(/\D/g, "").substring(0, 4);
605
- setCvv(value);
711
+ const handleCvvChange = (value) => {
712
+ const cleaned = value.replace(/\D/g, "");
713
+ setCvv(cleaned);
606
714
  if (errors.cvv) {
607
715
  setErrors({ ...errors, cvv: "" });
608
716
  }
717
+ onChange?.(getFormData());
609
718
  };
610
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: mergedStyles.container, className: className.container || "", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handleSubmit, style: mergedStyles.form, className: className.form || "", children: [
611
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
612
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.cardNumber }),
613
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative" }, children: [
614
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
615
- "input",
616
- {
617
- type: "text",
719
+ const handleCardHolderChange = (value) => {
720
+ setCardHolderName(value);
721
+ if (errors.cardHolder) {
722
+ setErrors({ ...errors, cardHolder: "" });
723
+ }
724
+ onChange?.(getFormData());
725
+ };
726
+ const handleEmailChange = (value) => {
727
+ setEmail(value);
728
+ if (errors.email) {
729
+ setErrors({ ...errors, email: "" });
730
+ }
731
+ onChange?.(getFormData());
732
+ };
733
+ const renderField = (fieldName) => {
734
+ const config = mergedFields[fieldName];
735
+ if (!config?.visible) return null;
736
+ const fieldRenderers = {
737
+ cardNumber: () => {
738
+ const label = config.label || mergedLabels.cardNumber;
739
+ const placeholder = config.placeholder || mergedPlaceholders.cardNumber;
740
+ const error = errors.cardNumber;
741
+ if (config.render) {
742
+ return config.render({
618
743
  value: cardNumber,
619
744
  onChange: handleCardNumberChange,
620
- placeholder: mergedPlaceholders.cardNumber,
621
- maxLength: 19,
622
- required: true,
623
- style: {
624
- ...mergedStyles.input,
625
- ...errors.cardNumber ? mergedStyles.inputError : {},
626
- paddingRight: showCardIcons ? "60px" : "16px"
745
+ onBlur: () => {
627
746
  },
628
- className: className.input || ""
629
- }
630
- ),
631
- showCardIcons && cardBrand !== "unknown" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
747
+ error,
748
+ placeholder,
749
+ label,
750
+ required: config.required !== false,
751
+ disabled: loading,
752
+ name: "card_number"
753
+ });
754
+ }
755
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
632
756
  "div",
633
757
  {
634
- style: {
635
- position: "absolute",
636
- right: "12px",
637
- top: "50%",
638
- transform: "translateY(-50%)"
639
- },
640
- children: mergedIcons[cardBrand]
758
+ style: { ...mergedStyles.inputGroup, ...config.style },
759
+ className: config.className || className.inputGroup,
760
+ children: [
761
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label, children: label }),
762
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative" }, children: [
763
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
764
+ "input",
765
+ {
766
+ type: "text",
767
+ value: cardNumber,
768
+ onChange: (e) => handleCardNumberChange(e.target.value),
769
+ placeholder,
770
+ maxLength: 19,
771
+ required: config.required !== false,
772
+ disabled: loading,
773
+ name: "card_number",
774
+ style: {
775
+ ...mergedStyles.input,
776
+ ...error ? mergedStyles.inputError : {},
777
+ paddingRight: showCardIcons ? "60px" : "16px"
778
+ },
779
+ className: className.input
780
+ }
781
+ ),
782
+ showCardIcons && cardBrand !== "unknown" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
783
+ "div",
784
+ {
785
+ style: {
786
+ position: "absolute",
787
+ right: "12px",
788
+ top: "50%",
789
+ transform: "translateY(-50%)"
790
+ },
791
+ children: mergedIcons[cardBrand]
792
+ }
793
+ )
794
+ ] }),
795
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: mergedStyles.errorMessage, children: error })
796
+ ]
641
797
  }
642
- )
643
- ] }),
644
- errors.cardNumber && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.cardNumber })
645
- ] }),
646
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
647
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.cardHolder }),
648
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
649
- "input",
650
- {
651
- type: "text",
652
- value: cardHolderName,
653
- onChange: (e) => {
654
- setCardHolderName(e.target.value);
655
- if (errors.cardHolder) {
656
- setErrors({ ...errors, cardHolder: "" });
657
- }
658
- },
659
- placeholder: mergedPlaceholders.cardHolder,
660
- required: true,
661
- style: {
662
- ...mergedStyles.input,
663
- ...errors.cardHolder ? mergedStyles.inputError : {}
664
- },
665
- className: className.input || ""
798
+ );
799
+ },
800
+ cardHolder: () => {
801
+ const label = config.label || mergedLabels.cardHolder;
802
+ const placeholder = config.placeholder || mergedPlaceholders.cardHolder;
803
+ const error = errors.cardHolder;
804
+ if (config.render) {
805
+ return config.render({
806
+ value: cardHolderName,
807
+ onChange: handleCardHolderChange,
808
+ onBlur: () => {
809
+ },
810
+ error,
811
+ placeholder,
812
+ label,
813
+ required: config.required !== false,
814
+ disabled: loading,
815
+ name: "card_holder_name"
816
+ });
666
817
  }
667
- ),
668
- errors.cardHolder && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.cardHolder })
669
- ] }),
670
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
671
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.customerEmail }),
672
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
673
- "input",
674
- {
675
- type: "email",
676
- value: email,
677
- onChange: (e) => {
678
- setEmail(e.target.value);
679
- if (errors.email) {
680
- setErrors({ ...errors, email: "" });
681
- }
682
- },
683
- placeholder: mergedPlaceholders.customerEmail,
684
- style: {
685
- ...mergedStyles.input,
686
- ...errors.email ? mergedStyles.inputError : {}
687
- },
688
- className: className.input || ""
818
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
819
+ "div",
820
+ {
821
+ style: { ...mergedStyles.inputGroup, ...config.style },
822
+ className: config.className || className.inputGroup,
823
+ children: [
824
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label, children: label }),
825
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
826
+ "input",
827
+ {
828
+ type: "text",
829
+ value: cardHolderName,
830
+ onChange: (e) => handleCardHolderChange(e.target.value),
831
+ placeholder,
832
+ required: config.required !== false,
833
+ disabled: loading,
834
+ name: "card_holder_name",
835
+ style: {
836
+ ...mergedStyles.input,
837
+ ...error ? mergedStyles.inputError : {}
838
+ },
839
+ className: className.input
840
+ }
841
+ ),
842
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: mergedStyles.errorMessage, children: error })
843
+ ]
844
+ }
845
+ );
846
+ },
847
+ customerEmail: () => {
848
+ const label = config.label || mergedLabels.customerEmail;
849
+ const placeholder = config.placeholder || mergedPlaceholders.customerEmail;
850
+ const error = errors.email;
851
+ if (config.render) {
852
+ return config.render({
853
+ value: email,
854
+ onChange: handleEmailChange,
855
+ onBlur: () => {
856
+ },
857
+ error,
858
+ placeholder,
859
+ label,
860
+ required: config.required === true,
861
+ disabled: loading,
862
+ name: "customer_email"
863
+ });
689
864
  }
690
- ),
691
- errors.email && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.email }),
692
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "12px", color: "#6B7280" }, children: "Used to associate the saved card with the customer" })
693
- ] }),
694
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: mergedStyles.row, children: [
695
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
696
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.expiryDate }),
697
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
698
- "input",
865
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
866
+ "div",
699
867
  {
700
- type: "text",
868
+ style: { ...mergedStyles.inputGroup, ...config.style },
869
+ className: config.className || className.inputGroup,
870
+ children: [
871
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label, children: label }),
872
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
873
+ "input",
874
+ {
875
+ type: "email",
876
+ value: email,
877
+ onChange: (e) => handleEmailChange(e.target.value),
878
+ placeholder,
879
+ required: config.required === true,
880
+ disabled: loading,
881
+ name: "customer_email",
882
+ style: {
883
+ ...mergedStyles.input,
884
+ ...error ? mergedStyles.inputError : {}
885
+ },
886
+ className: className.input
887
+ }
888
+ ),
889
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: mergedStyles.errorMessage, children: error }),
890
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: mergedStyles.helperText, children: "Used to associate the saved card with the customer" })
891
+ ]
892
+ }
893
+ );
894
+ },
895
+ expiryDate: () => {
896
+ const label = config.label || mergedLabels.expiryDate;
897
+ const placeholder = config.placeholder || mergedPlaceholders.expiryDate;
898
+ const error = errors.expiryDate;
899
+ if (config.render) {
900
+ return config.render({
701
901
  value: expiryDate,
702
902
  onChange: handleExpiryDateChange,
703
- placeholder: mergedPlaceholders.expiryDate,
704
- maxLength: 5,
705
- required: true,
706
- style: {
707
- ...mergedStyles.input,
708
- ...errors.expiryDate ? mergedStyles.inputError : {}
903
+ onBlur: () => {
709
904
  },
710
- className: className.input || ""
711
- }
712
- ),
713
- errors.expiryDate && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.expiryDate })
714
- ] }),
715
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
716
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.cvv }),
717
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
718
- "input",
905
+ error,
906
+ placeholder,
907
+ label,
908
+ required: config.required !== false,
909
+ disabled: loading,
910
+ name: "expiry_date"
911
+ });
912
+ }
913
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
914
+ "div",
719
915
  {
720
- type: "text",
916
+ style: { ...mergedStyles.inputGroup, ...config.style },
917
+ className: config.className || className.inputGroup,
918
+ children: [
919
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label, children: label }),
920
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
921
+ "input",
922
+ {
923
+ type: "text",
924
+ value: expiryDate,
925
+ onChange: (e) => handleExpiryDateChange(e.target.value),
926
+ placeholder,
927
+ maxLength: 5,
928
+ required: config.required !== false,
929
+ disabled: loading,
930
+ name: "expiry_date",
931
+ style: {
932
+ ...mergedStyles.input,
933
+ ...error ? mergedStyles.inputError : {}
934
+ },
935
+ className: className.input
936
+ }
937
+ ),
938
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: mergedStyles.errorMessage, children: error })
939
+ ]
940
+ }
941
+ );
942
+ },
943
+ cvv: () => {
944
+ const label = config.label || mergedLabels.cvv;
945
+ const placeholder = config.placeholder || mergedPlaceholders.cvv;
946
+ const error = errors.cvv;
947
+ if (config.render) {
948
+ return config.render({
721
949
  value: cvv,
722
950
  onChange: handleCvvChange,
723
- placeholder: mergedPlaceholders.cvv,
724
- maxLength: 4,
725
- required: true,
726
- style: {
727
- ...mergedStyles.input,
728
- ...errors.cvv ? mergedStyles.inputError : {}
951
+ onBlur: () => {
729
952
  },
730
- className: className.input || ""
953
+ error,
954
+ placeholder,
955
+ label,
956
+ required: config.required !== false,
957
+ disabled: loading,
958
+ name: "cvv"
959
+ });
960
+ }
961
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
962
+ "div",
963
+ {
964
+ style: { ...mergedStyles.inputGroup, ...config.style },
965
+ className: config.className || className.inputGroup,
966
+ children: [
967
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: mergedStyles.label, className: className.label, children: label }),
968
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
969
+ "input",
970
+ {
971
+ type: "text",
972
+ value: cvv,
973
+ onChange: (e) => handleCvvChange(e.target.value),
974
+ placeholder,
975
+ maxLength: 4,
976
+ required: config.required !== false,
977
+ disabled: loading,
978
+ name: "cvv",
979
+ style: {
980
+ ...mergedStyles.input,
981
+ ...error ? mergedStyles.inputError : {}
982
+ },
983
+ className: className.input
984
+ }
985
+ ),
986
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: mergedStyles.errorMessage, children: error })
987
+ ]
731
988
  }
732
- ),
733
- errors.cvv && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.cvv })
734
- ] })
735
- ] }),
736
- showSecurityNotice && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: mergedStyles.securityNotice, children: "\u{1F512} Your card details are securely processed by Amazon Payment Services. We never store your card information." }),
737
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
989
+ );
990
+ }
991
+ };
992
+ return fieldRenderers[fieldName]?.() || null;
993
+ };
994
+ const getFormStyle = () => {
995
+ const baseStyle = mergedStyles.form || {};
996
+ switch (layout.type) {
997
+ case "horizontal":
998
+ return {
999
+ ...baseStyle,
1000
+ flexDirection: "row",
1001
+ flexWrap: "wrap",
1002
+ gap: layout.gap || "12px"
1003
+ };
1004
+ case "grid":
1005
+ return {
1006
+ ...baseStyle,
1007
+ display: "grid",
1008
+ gridTemplateColumns: layout.gridTemplateColumns || `repeat(${layout.columns || 2}, 1fr)`,
1009
+ ...layout.gridTemplateAreas ? { gridTemplateAreas: layout.gridTemplateAreas } : {},
1010
+ gap: layout.gap || "12px"
1011
+ };
1012
+ case "custom":
1013
+ return {
1014
+ ...baseStyle,
1015
+ ...styles?.form || {}
1016
+ };
1017
+ default:
1018
+ return baseStyle;
1019
+ }
1020
+ };
1021
+ const renderSubmitButton = () => {
1022
+ if (submitButton) {
1023
+ if (typeof submitButton === "function") {
1024
+ return submitButton({ loading, onClick: () => {
1025
+ } });
1026
+ }
1027
+ return submitButton;
1028
+ }
1029
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
738
1030
  "button",
739
1031
  {
740
1032
  type: "submit",
@@ -743,11 +1035,37 @@ var TokenizationForm = ({
743
1035
  ...mergedStyles.button,
744
1036
  ...loading ? mergedStyles.buttonDisabled : {}
745
1037
  },
746
- className: className.button || "",
1038
+ className: className.button,
747
1039
  children: loading ? mergedLabels.processing : mergedLabels.submitButton
748
1040
  }
749
- )
750
- ] }) });
1041
+ );
1042
+ };
1043
+ const renderSecurityNotice = () => {
1044
+ if (!showSecurityNotice) return null;
1045
+ if (securityNotice) {
1046
+ return securityNotice;
1047
+ }
1048
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: mergedStyles.securityNotice, children: "\u{1F512} Your card details are securely processed by Amazon Payment Services. We never store your card information." });
1049
+ };
1050
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: mergedStyles.container, className: className.container, children: [
1051
+ beforeForm,
1052
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1053
+ "form",
1054
+ {
1055
+ onSubmit: handleSubmit,
1056
+ style: getFormStyle(),
1057
+ className: className.form,
1058
+ children: [
1059
+ fieldOrder.map((fieldName) => renderField(fieldName)),
1060
+ renderSecurityNotice(),
1061
+ beforeSubmit,
1062
+ renderSubmitButton(),
1063
+ afterSubmit
1064
+ ]
1065
+ }
1066
+ ),
1067
+ afterForm
1068
+ ] });
751
1069
  };
752
1070
 
753
1071
  // src/constants.ts