@sikka/aps 0.0.1 → 0.0.3

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