recur-tw 0.9.7 → 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +641 -719
- package/dist/index.d.cts +49 -38
- package/dist/index.d.ts +49 -38
- package/dist/index.js +641 -719
- package/dist/recur.umd.js +1027 -636
- package/dist/server.cjs +1 -1
- package/dist/server.d.cts +194 -0
- package/dist/server.d.ts +194 -0
- package/dist/server.js +1 -1
- package/package.json +4 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var litHtml = require('lit-html');
|
|
3
4
|
var React = require('react');
|
|
4
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
6
|
|
|
@@ -610,14 +611,28 @@ var init_skeleton_loader = __esm({
|
|
|
610
611
|
}
|
|
611
612
|
});
|
|
612
613
|
|
|
614
|
+
// src/components/styles/payment-form-skeleton.css
|
|
615
|
+
var payment_form_skeleton_default;
|
|
616
|
+
var init_payment_form_skeleton = __esm({
|
|
617
|
+
"src/components/styles/payment-form-skeleton.css"() {
|
|
618
|
+
payment_form_skeleton_default = "/**\n * Payment Form Skeleton - Shadow DOM Styles\n * Loading skeleton that matches the structure of RecurPaymentForm\n */\n\n:host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.payment-form-wrapper {\n max-width: 500px;\n margin: 0 auto;\n padding: 24px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n/* Header */\n.form-header {\n margin-bottom: 24px;\n}\n\n.form-title {\n font-size: 20px;\n font-weight: 600;\n color: #1a202c;\n margin: 0 0 4px 0;\n}\n\n.form-subtitle {\n font-size: 14px;\n color: #718096;\n margin: 0;\n}\n\n/* Sections */\n.form-section {\n margin-bottom: 24px;\n}\n\n.section-title {\n font-size: 14px;\n font-weight: 600;\n color: #2d3748;\n margin: 0 0 12px 0;\n}\n\n.label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n/* Skeleton base styles */\n.skeleton {\n background: linear-gradient(\n 90deg,\n #f0f0f0 0%,\n #e8e8e8 50%,\n #f0f0f0 100%\n );\n background-size: 200% 100%;\n animation: skeleton-loading 1.5s ease-in-out infinite;\n border-radius: 4px;\n}\n\n@keyframes skeleton-loading {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n}\n\n/* Order Summary */\n.order-summary {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n}\n\n.order-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.order-row:last-child {\n margin-bottom: 0;\n}\n\n.order-row--total {\n padding-top: 12px;\n border-top: 1px solid #e2e8f0;\n}\n\n.order-label {\n font-size: 14px;\n color: #4a5568;\n}\n\n.skeleton-order-value {\n height: 20px;\n width: 80px;\n}\n\n.skeleton-order-total {\n height: 26px;\n width: 100px;\n}\n\n/* Coupon Skeleton */\n.coupon-section {\n padding: 12px 0;\n border-top: 1px solid #e2e8f0;\n margin-top: 12px;\n min-height: 36px;\n display: flex;\n align-items: center;\n}\n\n.skeleton-coupon-trigger {\n height: 20px;\n width: 88px;\n}\n\n/* Customer Info Display */\n.customer-info-display {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 8px;\n}\n\n.info-row {\n margin-bottom: 12px;\n}\n\n.info-row:last-child {\n margin-bottom: 0;\n}\n\n.info-label {\n display: block;\n font-size: 12px;\n line-height: 16px;\n color: #718096;\n margin-bottom: 2px;\n}\n\n.skeleton-info-value {\n height: 20px;\n width: 120px;\n}\n\n/* Card Fields */\n.card-field {\n margin-bottom: 16px;\n}\n\n.card-field:last-child {\n margin-bottom: 0;\n}\n\n.skeleton-input {\n height: 36px;\n width: 100%;\n border-radius: 6px;\n}\n\n.card-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n column-gap: 16px;\n}\n\n/* Submit Button - matches .recur-submit-button: padding 14px*2 + font 16px * line-height ~1.5 */\n.skeleton-button {\n height: 52px;\n width: 100%;\n border-radius: 6px;\n}\n\n/* Security Note */\n.security-note {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n background: #f7fafc;\n border-radius: 6px;\n margin-top: 16px;\n}\n\n.security-icon {\n color: #48bb78;\n}\n\n.security-text {\n font-size: 13px;\n color: #4a5568;\n margin: 0;\n}\n";
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
|
|
613
622
|
// src/components/base/payment-form-skeleton.ts
|
|
614
623
|
var payment_form_skeleton_exports = {};
|
|
615
624
|
__export(payment_form_skeleton_exports, {
|
|
616
625
|
RecurPaymentFormSkeleton: () => RecurPaymentFormSkeleton
|
|
617
626
|
});
|
|
618
|
-
var RecurPaymentFormSkeleton;
|
|
619
|
-
var
|
|
627
|
+
var lockIcon, RecurPaymentFormSkeleton;
|
|
628
|
+
var init_payment_form_skeleton2 = __esm({
|
|
620
629
|
"src/components/base/payment-form-skeleton.ts"() {
|
|
630
|
+
init_payment_form_skeleton();
|
|
631
|
+
lockIcon = litHtml.html`
|
|
632
|
+
<svg class="security-icon" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
633
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
|
634
|
+
</svg>
|
|
635
|
+
`;
|
|
621
636
|
RecurPaymentFormSkeleton = class extends HTMLElement {
|
|
622
637
|
constructor() {
|
|
623
638
|
super();
|
|
@@ -626,275 +641,106 @@ var init_payment_form_skeleton = __esm({
|
|
|
626
641
|
connectedCallback() {
|
|
627
642
|
this.render();
|
|
628
643
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
.form-header {
|
|
647
|
-
margin-bottom: 24px;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
.form-title {
|
|
651
|
-
font-size: 20px;
|
|
652
|
-
font-weight: 600;
|
|
653
|
-
color: #1a202c;
|
|
654
|
-
margin: 0 0 4px 0;
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
.form-subtitle {
|
|
658
|
-
font-size: 14px;
|
|
659
|
-
color: #718096;
|
|
660
|
-
margin: 0;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
.form-section {
|
|
664
|
-
margin-bottom: 24px;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
.section-title {
|
|
668
|
-
font-size: 14px;
|
|
669
|
-
font-weight: 600;
|
|
670
|
-
color: #2d3748;
|
|
671
|
-
margin: 0 0 12px 0;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
.label {
|
|
675
|
-
display: block;
|
|
676
|
-
font-size: 14px;
|
|
677
|
-
font-weight: 500;
|
|
678
|
-
color: #2d3748;
|
|
679
|
-
margin-bottom: 6px;
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
/* Skeleton base styles */
|
|
683
|
-
.skeleton {
|
|
684
|
-
background: linear-gradient(
|
|
685
|
-
90deg,
|
|
686
|
-
#f0f0f0 0%,
|
|
687
|
-
#e8e8e8 50%,
|
|
688
|
-
#f0f0f0 100%
|
|
689
|
-
);
|
|
690
|
-
background-size: 200% 100%;
|
|
691
|
-
animation: skeleton-loading 1.5s ease-in-out infinite;
|
|
692
|
-
border-radius: 4px;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
@keyframes skeleton-loading {
|
|
696
|
-
0% {
|
|
697
|
-
background-position: 200% 0;
|
|
698
|
-
}
|
|
699
|
-
100% {
|
|
700
|
-
background-position: -200% 0;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
/* Order Summary */
|
|
705
|
-
.order-summary {
|
|
706
|
-
background: #f7fafc;
|
|
707
|
-
border: 1px solid #e2e8f0;
|
|
708
|
-
border-radius: 8px;
|
|
709
|
-
padding: 16px;
|
|
710
|
-
margin-bottom: 24px;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
.order-summary-title {
|
|
714
|
-
font-size: 14px;
|
|
715
|
-
font-weight: 600;
|
|
716
|
-
color: #2d3748;
|
|
717
|
-
margin: 0 0 12px 0;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
.order-row {
|
|
721
|
-
display: flex;
|
|
722
|
-
justify-content: space-between;
|
|
723
|
-
align-items: center;
|
|
724
|
-
margin-bottom: 8px;
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
.order-row:last-child {
|
|
728
|
-
margin-bottom: 0;
|
|
729
|
-
padding-top: 12px;
|
|
730
|
-
border-top: 1px solid #e2e8f0;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
.order-label {
|
|
734
|
-
font-size: 14px;
|
|
735
|
-
color: #4a5568;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
.skeleton-order-value {
|
|
739
|
-
height: 20px;
|
|
740
|
-
width: 80px;
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
.skeleton-order-total {
|
|
744
|
-
height: 26px;
|
|
745
|
-
width: 100px;
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
/* Customer Info Display */
|
|
749
|
-
.customer-info-display {
|
|
750
|
-
background: #f7fafc;
|
|
751
|
-
border: 1px solid #e2e8f0;
|
|
752
|
-
border-radius: 6px;
|
|
753
|
-
padding: 12px;
|
|
754
|
-
margin-bottom: 8px;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
.info-row {
|
|
758
|
-
margin-bottom: 12px;
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
.info-row:last-child {
|
|
762
|
-
margin-bottom: 0;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
.info-label {
|
|
766
|
-
display: block;
|
|
767
|
-
font-size: 12px;
|
|
768
|
-
line-height: 16px;
|
|
769
|
-
color: #718096;
|
|
770
|
-
margin-bottom: 2px;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
.skeleton-info-value {
|
|
774
|
-
height: 20px;
|
|
775
|
-
width: 120px;
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
/* Card Fields */
|
|
779
|
-
.card-field {
|
|
780
|
-
margin-bottom: 16px;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
.card-field:last-child {
|
|
784
|
-
margin-bottom: 0;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
.skeleton-input {
|
|
788
|
-
height: 36px;
|
|
789
|
-
width: 100%;
|
|
790
|
-
border-radius: 6px;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
.card-row {
|
|
794
|
-
display: grid;
|
|
795
|
-
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
796
|
-
column-gap: 16px;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
/* Submit Button - matches .recur-submit-button: padding 14px*2 + font 16px * line-height ~1.5 */
|
|
800
|
-
.skeleton-button {
|
|
801
|
-
height: 52px;
|
|
802
|
-
width: 100%;
|
|
803
|
-
border-radius: 6px;
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
/* Security Note */
|
|
807
|
-
.security-note {
|
|
808
|
-
display: flex;
|
|
809
|
-
align-items: center;
|
|
810
|
-
gap: 8px;
|
|
811
|
-
padding: 12px;
|
|
812
|
-
background: #f7fafc;
|
|
813
|
-
border-radius: 6px;
|
|
814
|
-
margin-top: 16px;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
.security-icon {
|
|
818
|
-
color: #48bb78;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
.security-text {
|
|
822
|
-
font-size: 13px;
|
|
823
|
-
color: #4a5568;
|
|
824
|
-
margin: 0;
|
|
825
|
-
}
|
|
826
|
-
</style>
|
|
827
|
-
|
|
828
|
-
<div class="payment-form-wrapper">
|
|
829
|
-
<!-- Header (matches payment-form.ts) -->
|
|
830
|
-
<div class="form-header">
|
|
831
|
-
<h2 class="form-title">\u8A02\u95B1\u4ED8\u6B3E</h2>
|
|
832
|
-
<p class="form-subtitle">\u8ACB\u586B\u5BEB\u4FE1\u7528\u5361\u8CC7\u8A0A\u5B8C\u6210\u8A02\u95B1</p>
|
|
833
|
-
</div>
|
|
834
|
-
|
|
835
|
-
<!-- Order Summary (matches createOrderSummarySection) -->
|
|
644
|
+
// ============================================
|
|
645
|
+
// Section Renderers
|
|
646
|
+
// ============================================
|
|
647
|
+
renderHeader() {
|
|
648
|
+
return litHtml.html`
|
|
649
|
+
<div class="form-header">
|
|
650
|
+
<h2 class="form-title">訂閱付款</h2>
|
|
651
|
+
</div>
|
|
652
|
+
`;
|
|
653
|
+
}
|
|
654
|
+
renderOrderSummary() {
|
|
655
|
+
return litHtml.html`
|
|
656
|
+
<div class="form-section">
|
|
657
|
+
<h3 class="section-title">訂單摘要</h3>
|
|
836
658
|
<div class="order-summary">
|
|
837
|
-
<h3 class="order-summary-title">\u8A02\u55AE\u6458\u8981</h3>
|
|
838
659
|
<div class="order-row">
|
|
839
|
-
<span class="order-label"
|
|
660
|
+
<span class="order-label">訂閱方案</span>
|
|
840
661
|
<div class="skeleton skeleton-order-value"></div>
|
|
841
662
|
</div>
|
|
842
663
|
<div class="order-row">
|
|
843
|
-
<span class="order-label"
|
|
664
|
+
<span class="order-label">計費週期</span>
|
|
844
665
|
<div class="skeleton skeleton-order-value"></div>
|
|
845
666
|
</div>
|
|
846
|
-
<div class="
|
|
847
|
-
<
|
|
667
|
+
<div class="coupon-section">
|
|
668
|
+
<div class="skeleton skeleton-coupon-trigger"></div>
|
|
669
|
+
</div>
|
|
670
|
+
<div class="order-row order-row--total">
|
|
671
|
+
<span class="order-label">總計</span>
|
|
848
672
|
<div class="skeleton skeleton-order-total"></div>
|
|
849
673
|
</div>
|
|
850
674
|
</div>
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
<
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
675
|
+
</div>
|
|
676
|
+
`;
|
|
677
|
+
}
|
|
678
|
+
renderCustomerInfo() {
|
|
679
|
+
return litHtml.html`
|
|
680
|
+
<div class="form-section">
|
|
681
|
+
<h3 class="section-title">聯絡資訊</h3>
|
|
682
|
+
<div class="customer-info-display">
|
|
683
|
+
<div class="info-row">
|
|
684
|
+
<span class="info-label">姓名</span>
|
|
685
|
+
<div class="skeleton skeleton-info-value"></div>
|
|
686
|
+
</div>
|
|
687
|
+
<div class="info-row">
|
|
688
|
+
<span class="info-label">電子郵件</span>
|
|
689
|
+
<div class="skeleton skeleton-info-value" style="width: 160px;"></div>
|
|
864
690
|
</div>
|
|
865
691
|
</div>
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
692
|
+
</div>
|
|
693
|
+
`;
|
|
694
|
+
}
|
|
695
|
+
renderCardFields() {
|
|
696
|
+
return litHtml.html`
|
|
697
|
+
<div class="form-section">
|
|
698
|
+
<h3 class="section-title">信用卡資訊</h3>
|
|
699
|
+
<div class="card-field">
|
|
700
|
+
<label class="label">卡號</label>
|
|
701
|
+
<div class="skeleton skeleton-input"></div>
|
|
702
|
+
</div>
|
|
703
|
+
<div class="card-row">
|
|
870
704
|
<div class="card-field">
|
|
871
|
-
<label class="label"
|
|
705
|
+
<label class="label">有效期限</label>
|
|
872
706
|
<div class="skeleton skeleton-input"></div>
|
|
873
707
|
</div>
|
|
874
|
-
<div class="card-
|
|
875
|
-
<
|
|
876
|
-
|
|
877
|
-
<div class="skeleton skeleton-input"></div>
|
|
878
|
-
</div>
|
|
879
|
-
<div class="card-field">
|
|
880
|
-
<label class="label">\u5B89\u5168\u78BC</label>
|
|
881
|
-
<div class="skeleton skeleton-input"></div>
|
|
882
|
-
</div>
|
|
708
|
+
<div class="card-field">
|
|
709
|
+
<label class="label">安全碼</label>
|
|
710
|
+
<div class="skeleton skeleton-input"></div>
|
|
883
711
|
</div>
|
|
884
712
|
</div>
|
|
713
|
+
</div>
|
|
714
|
+
`;
|
|
715
|
+
}
|
|
716
|
+
renderSubmitButton() {
|
|
717
|
+
return litHtml.html`<div class="skeleton skeleton-button"></div>`;
|
|
718
|
+
}
|
|
719
|
+
renderSecurityNote() {
|
|
720
|
+
return litHtml.html`
|
|
721
|
+
<div class="security-note">
|
|
722
|
+
${lockIcon}
|
|
723
|
+
<p class="security-text">您的付款資訊經過加密保護</p>
|
|
724
|
+
</div>
|
|
725
|
+
`;
|
|
726
|
+
}
|
|
727
|
+
// ============================================
|
|
728
|
+
// Main Render
|
|
729
|
+
// ============================================
|
|
730
|
+
render() {
|
|
731
|
+
const template = litHtml.html`
|
|
732
|
+
<style>${payment_form_skeleton_default}</style>
|
|
885
733
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
</svg>
|
|
894
|
-
<p class="security-text">\u60A8\u7684\u4ED8\u6B3E\u8CC7\u8A0A\u7D93\u904E\u52A0\u5BC6\u4FDD\u8B77</p>
|
|
895
|
-
</div>
|
|
734
|
+
<div class="payment-form-wrapper">
|
|
735
|
+
${this.renderHeader()}
|
|
736
|
+
${this.renderOrderSummary()}
|
|
737
|
+
${this.renderCustomerInfo()}
|
|
738
|
+
${this.renderCardFields()}
|
|
739
|
+
${this.renderSubmitButton()}
|
|
740
|
+
${this.renderSecurityNote()}
|
|
896
741
|
</div>
|
|
897
742
|
`;
|
|
743
|
+
litHtml.render(template, this.shadowRoot);
|
|
898
744
|
}
|
|
899
745
|
};
|
|
900
746
|
if (typeof window !== "undefined" && !customElements.get("recur-payment-form-skeleton")) {
|
|
@@ -1177,14 +1023,55 @@ var init_toast = __esm({
|
|
|
1177
1023
|
}
|
|
1178
1024
|
});
|
|
1179
1025
|
|
|
1026
|
+
// src/components/styles/payment-form-shadow.css
|
|
1027
|
+
var payment_form_shadow_default;
|
|
1028
|
+
var init_payment_form_shadow = __esm({
|
|
1029
|
+
"src/components/styles/payment-form-shadow.css"() {
|
|
1030
|
+
payment_form_shadow_default = "/**\n * Payment Form - Shadow DOM Styles\n * These styles are encapsulated within the Shadow DOM\n */\n\n:host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.payment-form-wrapper {\n max-width: 500px;\n margin: 0 auto;\n padding: 24px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n touch-action: manipulation;\n container-type: inline-size;\n}\n\n.form-header {\n margin-bottom: 24px;\n}\n\n.form-title {\n font-size: 20px;\n font-weight: 600;\n color: #1a202c;\n margin: 0 0 4px 0;\n}\n\n.form-subtitle {\n font-size: 14px;\n color: #718096;\n margin: 0;\n}\n\n.form-section {\n margin-bottom: 24px;\n}\n\n.section-title {\n font-size: 14px;\n font-weight: 600;\n color: #2d3748;\n margin: 0 0 12px 0;\n}\n\n::slotted(*) {\n display: block;\n}\n\n.security-note {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n background: #f7fafc;\n border-radius: 6px;\n margin-top: 16px;\n}\n\n.security-icon {\n color: #48bb78;\n}\n\n.security-text {\n font-size: 13px;\n color: #4a5568;\n margin: 0;\n}\n";
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
|
|
1034
|
+
// src/components/styles/payment-form-light.css
|
|
1035
|
+
var payment_form_light_default;
|
|
1036
|
+
var init_payment_form_light = __esm({
|
|
1037
|
+
"src/components/styles/payment-form-light.css"() {
|
|
1038
|
+
payment_form_light_default = "/**\n * Payment Form - Light DOM Styles\n * These styles are applied to slotted content in the Light DOM\n * Using BEM naming convention with 'recur-' prefix for isolation\n */\n\n/* ============================================\n * Order Summary Styles\n * ============================================ */\n.recur-order-summary {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n}\n\n.recur-order-summary__row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.recur-order-summary__row--total {\n margin-bottom: 0;\n padding-top: 12px;\n border-top: 1px solid #e2e8f0;\n}\n\n.recur-order-summary__label {\n font-size: 14px;\n color: #4a5568;\n}\n\n.recur-order-summary__value {\n font-size: 14px;\n line-height: 20px;\n font-weight: 500;\n color: #2d3748;\n}\n\n.recur-order-summary__total {\n font-size: 18px;\n line-height: 26px;\n font-weight: 700;\n color: #1a202c;\n}\n\n/* ============================================\n * Coupon Section Styles\n * ============================================ */\n.recur-coupon {\n padding: 12px 0;\n border-top: 1px solid #e2e8f0;\n margin-top: 12px;\n min-height: 36px;\n display: flex;\n align-items: center;\n}\n\n.recur-coupon__trigger {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 36px;\n background: none;\n border: none;\n padding: 0;\n font-size: 14px;\n line-height: 1;\n color: #718096;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.recur-coupon__trigger:hover {\n color: #4a5568;\n}\n\n.recur-coupon__trigger-icon {\n width: 16px;\n height: 16px;\n}\n\n.recur-coupon__input-row {\n display: flex;\n gap: 8px;\n width: 100%;\n}\n\n.recur-coupon__input {\n flex: 1;\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n text-transform: uppercase;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n outline: none;\n transition: border-color 0.2s, box-shadow 0.2s;\n}\n\n.recur-coupon__input::placeholder {\n text-transform: none;\n}\n\n.recur-coupon__input:focus {\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.recur-coupon__btn {\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s, opacity 0.2s;\n white-space: nowrap;\n}\n\n.recur-coupon__btn--apply {\n background: #18181b;\n color: white;\n border: none;\n}\n\n.recur-coupon__btn--apply:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-coupon__btn--apply:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.recur-coupon__btn--cancel {\n background: transparent;\n color: #718096;\n border: 1px solid #d1d5db;\n}\n\n.recur-coupon__btn--cancel:hover {\n background: #f7fafc;\n}\n\n.recur-coupon__error {\n width: 100%;\n margin-top: 8px;\n font-size: 13px;\n color: #dc2626;\n}\n\n.recur-coupon__applied {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n}\n\n.recur-coupon__applied-info {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n min-width: 0;\n}\n\n.recur-coupon__applied-icon {\n width: 16px;\n height: 16px;\n color: #16a34a;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.recur-coupon__applied-details {\n min-width: 0;\n}\n\n.recur-coupon__applied-name {\n font-size: 14px;\n font-weight: 500;\n color: #16a34a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.recur-coupon__applied-code {\n font-size: 12px;\n color: #718096;\n}\n\n.recur-coupon__applied-amount {\n font-size: 14px;\n font-weight: 500;\n color: #16a34a;\n white-space: nowrap;\n}\n\n.recur-coupon__remove {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #9ca3af;\n border-radius: 4px;\n transition: color 0.2s, background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.recur-coupon__remove:hover {\n color: #6b7280;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.recur-coupon__remove-icon {\n width: 14px;\n height: 14px;\n}\n\n.recur-coupon__spinner {\n width: 14px;\n height: 14px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n/* Discount Row */\n.recur-order-summary__row--discount {\n color: #16a34a;\n}\n\n.recur-order-summary__row--discount .recur-order-summary__value {\n color: #16a34a;\n font-weight: 500;\n}\n\n/* ============================================\n * Customer Info Styles\n * ============================================ */\n.recur-info-display {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 8px;\n}\n\n.recur-info-row {\n margin-bottom: 12px;\n}\n\n.recur-info-row:last-child {\n margin-bottom: 0;\n}\n\n.recur-info-label {\n display: block;\n font-size: 12px;\n line-height: 16px;\n color: #718096;\n margin-bottom: 2px;\n}\n\n.recur-info-value {\n display: block;\n font-size: 14px;\n line-height: 20px;\n min-height: 20px;\n color: #2d3748;\n font-weight: 500;\n word-break: break-all;\n}\n\n.recur-form-group {\n margin-bottom: 16px;\n}\n\n.recur-form-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-form-input {\n width: 100%;\n padding: 10px 12px;\n font-size: 16px;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n transition: border-color 0.2s;\n box-sizing: border-box;\n}\n\n.recur-form-input:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.recur-form-input:hover:not(:focus) {\n border-color: #9ca3af;\n}\n\n/* ============================================\n * Card Fields Styles\n * ============================================ */\n.recur-card-field {\n margin-bottom: 16px;\n}\n\n.recur-card-field-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-payuni-iframe {\n height: 36px;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n touch-action: manipulation;\n}\n\n.recur-card-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n column-gap: 16px;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n.recur-card-field-container {\n position: relative;\n touch-action: manipulation;\n}\n\n.recur-card-skeleton {\n position: absolute;\n top: 0;\n left: 0;\n height: 36px;\n width: 100%;\n background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);\n background-size: 200% 100%;\n animation: recur-skeleton-loading 1.5s ease-in-out infinite;\n border-radius: 4px;\n z-index: 1;\n pointer-events: none;\n}\n\n.recur-card-skeleton.hidden {\n display: none;\n}\n\n@keyframes recur-skeleton-loading {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n/* ============================================\n * Submit Button Styles\n * ============================================ */\n.recur-submit-button {\n width: 100%;\n padding: 14px 20px;\n font-size: 16px;\n font-weight: 500;\n color: #ffffff;\n background: #18181b;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n box-sizing: border-box;\n}\n\n.recur-submit-button:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-submit-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.recur-submit-button.loading {\n cursor: wait;\n}\n\n.recur-loading-spinner {\n width: 16px;\n height: 16px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n@keyframes recur-spin {\n to { transform: rotate(360deg); }\n}\n";
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
|
|
1180
1042
|
// src/components/payment-form.ts
|
|
1181
1043
|
var payment_form_exports = {};
|
|
1182
1044
|
__export(payment_form_exports, {
|
|
1183
1045
|
RecurPaymentForm: () => RecurPaymentForm
|
|
1184
1046
|
});
|
|
1185
|
-
var RecurPaymentForm;
|
|
1047
|
+
var icons, RecurPaymentForm;
|
|
1186
1048
|
var init_payment_form = __esm({
|
|
1187
1049
|
"src/components/payment-form.ts"() {
|
|
1050
|
+
init_payment_form_shadow();
|
|
1051
|
+
init_payment_form_light();
|
|
1052
|
+
icons = {
|
|
1053
|
+
lock: litHtml.html`
|
|
1054
|
+
<svg class="security-icon" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1055
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
|
1056
|
+
</svg>
|
|
1057
|
+
`,
|
|
1058
|
+
tag: litHtml.html`
|
|
1059
|
+
<svg class="recur-coupon__trigger-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1060
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
|
|
1061
|
+
</svg>
|
|
1062
|
+
`,
|
|
1063
|
+
tagApplied: litHtml.html`
|
|
1064
|
+
<svg class="recur-coupon__applied-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1065
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
|
|
1066
|
+
</svg>
|
|
1067
|
+
`,
|
|
1068
|
+
close: litHtml.html`
|
|
1069
|
+
<svg class="recur-coupon__remove-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1070
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
|
1071
|
+
</svg>
|
|
1072
|
+
`,
|
|
1073
|
+
spinner: litHtml.html`<span class="recur-coupon__spinner"></span>`
|
|
1074
|
+
};
|
|
1188
1075
|
RecurPaymentForm = class extends HTMLElement {
|
|
1189
1076
|
constructor() {
|
|
1190
1077
|
super();
|
|
@@ -1192,6 +1079,12 @@ var init_payment_form = __esm({
|
|
|
1192
1079
|
__publicField(this, "customStyles");
|
|
1193
1080
|
__publicField(this, "_isInitializing", false);
|
|
1194
1081
|
__publicField(this, "_initializationAborted", false);
|
|
1082
|
+
// Coupon state
|
|
1083
|
+
__publicField(this, "_showCouponInput", false);
|
|
1084
|
+
__publicField(this, "_couponCode", "");
|
|
1085
|
+
__publicField(this, "_couponLoading", false);
|
|
1086
|
+
__publicField(this, "_couponError", null);
|
|
1087
|
+
__publicField(this, "_appliedCoupon", null);
|
|
1195
1088
|
this.containerId = this.getAttribute("container-id") || `recur-${Date.now()}`;
|
|
1196
1089
|
this.customStyles = this.getAttribute("custom-styles") || "";
|
|
1197
1090
|
this.attachShadow({ mode: "open" });
|
|
@@ -1209,183 +1102,129 @@ var init_payment_form = __esm({
|
|
|
1209
1102
|
submitBtn.parentNode?.replaceChild(newBtn, submitBtn);
|
|
1210
1103
|
}
|
|
1211
1104
|
}
|
|
1212
|
-
// 監聽 attribute 變化
|
|
1213
1105
|
static get observedAttributes() {
|
|
1214
|
-
return [
|
|
1106
|
+
return [
|
|
1107
|
+
"custom-styles",
|
|
1108
|
+
"customer-name",
|
|
1109
|
+
"customer-email",
|
|
1110
|
+
"product-name",
|
|
1111
|
+
"amount",
|
|
1112
|
+
"interval",
|
|
1113
|
+
"checkout-id",
|
|
1114
|
+
"publishable-key",
|
|
1115
|
+
"api-base-url"
|
|
1116
|
+
];
|
|
1215
1117
|
}
|
|
1216
1118
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
1217
|
-
if (
|
|
1119
|
+
if (oldValue === newValue) return;
|
|
1120
|
+
if (name === "custom-styles") {
|
|
1218
1121
|
this.customStyles = newValue || "";
|
|
1219
1122
|
this.updateCustomStyles();
|
|
1220
|
-
} else
|
|
1221
|
-
this.
|
|
1123
|
+
} else {
|
|
1124
|
+
this.updateOrderSummaryDOM();
|
|
1222
1125
|
}
|
|
1223
1126
|
}
|
|
1127
|
+
// ============================================
|
|
1128
|
+
// Styles
|
|
1129
|
+
// ============================================
|
|
1130
|
+
getShadowDOMStyles() {
|
|
1131
|
+
return payment_form_shadow_default;
|
|
1132
|
+
}
|
|
1133
|
+
getLightDOMStyles() {
|
|
1134
|
+
return payment_form_light_default;
|
|
1135
|
+
}
|
|
1136
|
+
// ============================================
|
|
1137
|
+
// Render Methods
|
|
1138
|
+
// ============================================
|
|
1224
1139
|
render() {
|
|
1225
|
-
this.
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
.payment-form-wrapper {
|
|
1233
|
-
max-width: 500px;
|
|
1234
|
-
margin: 0 auto;
|
|
1235
|
-
padding: 24px;
|
|
1236
|
-
background: white;
|
|
1237
|
-
border-radius: 12px;
|
|
1238
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
1239
|
-
/* Prevent double-tap zoom on iOS */
|
|
1240
|
-
touch-action: manipulation;
|
|
1241
|
-
/* Enable container queries for responsive layout */
|
|
1242
|
-
container-type: inline-size;
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
.form-header {
|
|
1246
|
-
margin-bottom: 24px;
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
.form-title {
|
|
1250
|
-
font-size: 20px;
|
|
1251
|
-
font-weight: 600;
|
|
1252
|
-
color: #1a202c;
|
|
1253
|
-
margin: 0 0 4px 0;
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
.form-subtitle {
|
|
1257
|
-
font-size: 14px;
|
|
1258
|
-
color: #718096;
|
|
1259
|
-
margin: 0;
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
.form-section {
|
|
1263
|
-
margin-bottom: 24px;
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
.section-title {
|
|
1267
|
-
font-size: 14px;
|
|
1268
|
-
font-weight: 600;
|
|
1269
|
-
color: #2d3748;
|
|
1270
|
-
margin: 0 0 12px 0;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
::slotted(*) {
|
|
1274
|
-
display: block;
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
.security-note {
|
|
1278
|
-
display: flex;
|
|
1279
|
-
align-items: center;
|
|
1280
|
-
gap: 8px;
|
|
1281
|
-
padding: 12px;
|
|
1282
|
-
background: #f7fafc;
|
|
1283
|
-
border-radius: 6px;
|
|
1284
|
-
margin-top: 16px;
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
.security-icon {
|
|
1288
|
-
color: #48bb78;
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
.security-text {
|
|
1292
|
-
font-size: 13px;
|
|
1293
|
-
color: #4a5568;
|
|
1294
|
-
margin: 0;
|
|
1295
|
-
}
|
|
1296
|
-
</style>
|
|
1140
|
+
this.renderShadowDOM();
|
|
1141
|
+
this.renderLightDOM();
|
|
1142
|
+
}
|
|
1143
|
+
renderShadowDOM() {
|
|
1144
|
+
const template = litHtml.html`
|
|
1145
|
+
<style>${this.getShadowDOMStyles()}</style>
|
|
1297
1146
|
|
|
1298
1147
|
<div class="payment-form-wrapper">
|
|
1299
1148
|
<div class="form-header">
|
|
1300
|
-
<h2 class="form-title"
|
|
1301
|
-
<p class="form-subtitle">\u8ACB\u586B\u5BEB\u4FE1\u7528\u5361\u8CC7\u8A0A\u5B8C\u6210\u8A02\u95B1</p>
|
|
1149
|
+
<h2 class="form-title">訂閱付款</h2>
|
|
1302
1150
|
</div>
|
|
1303
1151
|
|
|
1304
|
-
|
|
1305
|
-
|
|
1152
|
+
<div class="form-section">
|
|
1153
|
+
<h3 class="section-title">訂單摘要</h3>
|
|
1154
|
+
<slot name="order-summary"></slot>
|
|
1155
|
+
</div>
|
|
1306
1156
|
|
|
1307
1157
|
<div class="form-section">
|
|
1308
|
-
<h3 class="section-title"
|
|
1309
|
-
<!-- Slot for customer info fields (Light DOM) -->
|
|
1158
|
+
<h3 class="section-title">聯絡資訊</h3>
|
|
1310
1159
|
<slot name="customer-info"></slot>
|
|
1311
1160
|
</div>
|
|
1312
1161
|
|
|
1313
1162
|
<div class="form-section">
|
|
1314
|
-
<h3 class="section-title"
|
|
1315
|
-
<!-- Slot for PAYUNi card fields (Light DOM) -->
|
|
1163
|
+
<h3 class="section-title">信用卡資訊</h3>
|
|
1316
1164
|
<slot name="card-fields"></slot>
|
|
1317
1165
|
</div>
|
|
1318
1166
|
|
|
1319
|
-
<!-- Slot for submit button (Light DOM) -->
|
|
1320
1167
|
<slot name="actions"></slot>
|
|
1321
1168
|
|
|
1322
1169
|
<div class="security-note">
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
</svg>
|
|
1326
|
-
<p class="security-text">\u60A8\u7684\u4ED8\u6B3E\u8CC7\u8A0A\u7D93\u904E\u52A0\u5BC6\u4FDD\u8B77</p>
|
|
1170
|
+
${icons.lock}
|
|
1171
|
+
<p class="security-text">您的付款資訊經過加密保護</p>
|
|
1327
1172
|
</div>
|
|
1328
1173
|
</div>
|
|
1329
1174
|
`;
|
|
1330
|
-
this.
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1175
|
+
litHtml.render(template, this.shadowRoot);
|
|
1176
|
+
}
|
|
1177
|
+
renderLightDOM() {
|
|
1178
|
+
const template = litHtml.html`
|
|
1179
|
+
<style id="${this.containerId}-styles">
|
|
1180
|
+
${this.getLightDOMStyles()}
|
|
1181
|
+
${this.getCustomStyles()}
|
|
1182
|
+
</style>
|
|
1183
|
+
|
|
1184
|
+
<div slot="order-summary">
|
|
1185
|
+
${this.renderOrderSummary()}
|
|
1186
|
+
</div>
|
|
1187
|
+
|
|
1188
|
+
<div slot="customer-info">
|
|
1189
|
+
${this.renderCustomerInfo()}
|
|
1190
|
+
</div>
|
|
1191
|
+
|
|
1192
|
+
<div slot="card-fields">
|
|
1193
|
+
${this.renderCardFields()}
|
|
1194
|
+
</div>
|
|
1195
|
+
|
|
1196
|
+
<div slot="actions">
|
|
1197
|
+
${this.renderActions()}
|
|
1198
|
+
</div>
|
|
1199
|
+
`;
|
|
1200
|
+
litHtml.render(template, this);
|
|
1201
|
+
}
|
|
1202
|
+
getCustomStyles() {
|
|
1203
|
+
return `
|
|
1204
|
+
/* PAYUNi iframe container height */
|
|
1338
1205
|
#${this.containerId}-card-no,
|
|
1339
1206
|
#${this.containerId}-card-exp,
|
|
1340
1207
|
#${this.containerId}-card-cvc {
|
|
1341
1208
|
height: 36px !important;
|
|
1342
1209
|
}
|
|
1210
|
+
${this.customStyles}
|
|
1343
1211
|
`;
|
|
1344
|
-
styleElement.textContent = this.customStyles + "\n" + idSpecificStyles;
|
|
1345
|
-
this.appendChild(styleElement);
|
|
1346
|
-
const orderSummary = this.createOrderSummarySection();
|
|
1347
|
-
orderSummary.slot = "order-summary";
|
|
1348
|
-
this.appendChild(orderSummary);
|
|
1349
|
-
const customerInfo = this.createCustomerInfoSection();
|
|
1350
|
-
customerInfo.slot = "customer-info";
|
|
1351
|
-
this.appendChild(customerInfo);
|
|
1352
|
-
const cardFields = this.createCardFieldsSection();
|
|
1353
|
-
cardFields.slot = "card-fields";
|
|
1354
|
-
this.appendChild(cardFields);
|
|
1355
|
-
const actions = this.createActionsSection();
|
|
1356
|
-
actions.slot = "actions";
|
|
1357
|
-
this.appendChild(actions);
|
|
1358
|
-
}
|
|
1359
|
-
updateCustomerInfoSection() {
|
|
1360
|
-
const existingSection = this.querySelector('[slot="customer-info"]');
|
|
1361
|
-
if (existingSection) {
|
|
1362
|
-
const newSection = this.createCustomerInfoSection();
|
|
1363
|
-
newSection.slot = "customer-info";
|
|
1364
|
-
existingSection.replaceWith(newSection);
|
|
1365
|
-
}
|
|
1366
1212
|
}
|
|
1367
1213
|
updateCustomStyles() {
|
|
1368
|
-
const styleElement = this.querySelector(`#${this.containerId}-
|
|
1214
|
+
const styleElement = this.querySelector(`#${this.containerId}-styles`);
|
|
1369
1215
|
if (styleElement) {
|
|
1370
|
-
|
|
1371
|
-
/* PAYUNi iframe \u5BB9\u5668\u9AD8\u5EA6\uFF08\u4F7F\u7528\u5BE6\u969B\u7684 container ID\uFF09 */
|
|
1372
|
-
#${this.containerId}-card-no,
|
|
1373
|
-
#${this.containerId}-card-exp,
|
|
1374
|
-
#${this.containerId}-card-cvc {
|
|
1375
|
-
height: 36px !important;
|
|
1376
|
-
}
|
|
1377
|
-
`;
|
|
1378
|
-
styleElement.textContent = this.customStyles + "\n" + idSpecificStyles;
|
|
1216
|
+
styleElement.textContent = this.getLightDOMStyles() + this.getCustomStyles();
|
|
1379
1217
|
}
|
|
1380
1218
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1219
|
+
// ============================================
|
|
1220
|
+
// Section Renderers (lit-html)
|
|
1221
|
+
// ============================================
|
|
1222
|
+
renderOrderSummary() {
|
|
1384
1223
|
const productName = this.getAttribute("product-name");
|
|
1385
1224
|
const amount = this.getAttribute("amount");
|
|
1386
1225
|
const interval = this.getAttribute("interval");
|
|
1387
1226
|
if (!productName || !amount) {
|
|
1388
|
-
return
|
|
1227
|
+
return litHtml.html`<div class="recur-order-summary" style="display: none;"></div>`;
|
|
1389
1228
|
}
|
|
1390
1229
|
const intervalMap = {
|
|
1391
1230
|
"day": "\u65E5",
|
|
@@ -1394,275 +1233,444 @@ var init_payment_form = __esm({
|
|
|
1394
1233
|
"year": "\u5E74"
|
|
1395
1234
|
};
|
|
1396
1235
|
const periodText = interval ? intervalMap[interval] || interval : "";
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
.order-summary-title {
|
|
1408
|
-
font-size: 14px;
|
|
1409
|
-
font-weight: 600;
|
|
1410
|
-
color: #2d3748;
|
|
1411
|
-
margin: 0 0 12px 0;
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
.order-summary-item {
|
|
1415
|
-
display: flex;
|
|
1416
|
-
justify-content: space-between;
|
|
1417
|
-
align-items: center;
|
|
1418
|
-
margin-bottom: 8px;
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
.order-summary-item:last-child {
|
|
1422
|
-
margin-bottom: 0;
|
|
1423
|
-
padding-top: 12px;
|
|
1424
|
-
border-top: 1px solid #e2e8f0;
|
|
1425
|
-
}
|
|
1236
|
+
const originalAmount = Number(amount);
|
|
1237
|
+
const discountAmount = this._appliedCoupon?.discountAmount || 0;
|
|
1238
|
+
const finalAmount = originalAmount - discountAmount;
|
|
1239
|
+
return litHtml.html`
|
|
1240
|
+
<div class="recur-order-summary" id="${this.containerId}-order-summary">
|
|
1241
|
+
<div class="recur-order-summary__row">
|
|
1242
|
+
<span class="recur-order-summary__label">訂閱方案</span>
|
|
1243
|
+
<span class="recur-order-summary__value">${productName}</span>
|
|
1244
|
+
</div>
|
|
1426
1245
|
|
|
1427
|
-
.
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1246
|
+
${periodText ? litHtml.html`
|
|
1247
|
+
<div class="recur-order-summary__row">
|
|
1248
|
+
<span class="recur-order-summary__label">計費週期</span>
|
|
1249
|
+
<span class="recur-order-summary__value">每${periodText}</span>
|
|
1250
|
+
</div>
|
|
1251
|
+
` : litHtml.nothing}
|
|
1431
1252
|
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
font-weight: 500;
|
|
1436
|
-
color: #2d3748;
|
|
1437
|
-
}
|
|
1253
|
+
<div class="recur-coupon" id="${this.containerId}-coupon">
|
|
1254
|
+
${this.renderCoupon()}
|
|
1255
|
+
</div>
|
|
1438
1256
|
|
|
1439
|
-
.
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1257
|
+
${discountAmount > 0 ? litHtml.html`
|
|
1258
|
+
<div class="recur-order-summary__row">
|
|
1259
|
+
<span class="recur-order-summary__label">小計</span>
|
|
1260
|
+
<span class="recur-order-summary__value">NT$ ${originalAmount.toLocaleString()}</span>
|
|
1261
|
+
</div>
|
|
1262
|
+
<div class="recur-order-summary__row recur-order-summary__row--discount">
|
|
1263
|
+
<span class="recur-order-summary__label">折扣</span>
|
|
1264
|
+
<span class="recur-order-summary__value">-NT$ ${discountAmount.toLocaleString()}</span>
|
|
1265
|
+
</div>
|
|
1266
|
+
` : litHtml.nothing}
|
|
1446
1267
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
<span class="order-summary-value">${productName}</span>
|
|
1451
|
-
</div>
|
|
1452
|
-
${periodText ? `
|
|
1453
|
-
<div class="order-summary-item">
|
|
1454
|
-
<span class="order-summary-label">\u8A08\u8CBB\u9031\u671F</span>
|
|
1455
|
-
<span class="order-summary-value">\u6BCF${periodText}</span>
|
|
1268
|
+
<div class="recur-order-summary__row recur-order-summary__row--total">
|
|
1269
|
+
<span class="recur-order-summary__label">總計</span>
|
|
1270
|
+
<span class="recur-order-summary__total">NT$ ${finalAmount.toLocaleString()}</span>
|
|
1456
1271
|
</div>
|
|
1457
|
-
` : ""}
|
|
1458
|
-
<div class="order-summary-item">
|
|
1459
|
-
<span class="order-summary-label">\u7E3D\u8A08</span>
|
|
1460
|
-
<span class="order-summary-total">NT$ ${Number(amount).toLocaleString()}</span>
|
|
1461
1272
|
</div>
|
|
1462
1273
|
`;
|
|
1463
|
-
return section;
|
|
1464
1274
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
margin-bottom: 8px;
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
.recur-info-row {
|
|
1482
|
-
margin-bottom: 12px;
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
.recur-info-row:last-child {
|
|
1486
|
-
margin-bottom: 0;
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
|
-
.recur-info-label {
|
|
1490
|
-
display: block;
|
|
1491
|
-
font-size: 12px;
|
|
1492
|
-
line-height: 16px;
|
|
1493
|
-
color: #718096;
|
|
1494
|
-
margin-bottom: 2px;
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
.recur-info-value {
|
|
1498
|
-
display: block;
|
|
1499
|
-
font-size: 14px;
|
|
1500
|
-
line-height: 20px;
|
|
1501
|
-
min-height: 20px;
|
|
1502
|
-
color: #2d3748;
|
|
1503
|
-
font-weight: 500;
|
|
1504
|
-
word-break: break-all;
|
|
1505
|
-
}
|
|
1506
|
-
</style>
|
|
1507
|
-
|
|
1508
|
-
<div class="recur-info-display">
|
|
1509
|
-
${customerName ? `
|
|
1510
|
-
<div class="recur-info-row">
|
|
1511
|
-
<span class="recur-info-label">\u59D3\u540D</span>
|
|
1512
|
-
<span class="recur-info-value">${customerName}</span>
|
|
1275
|
+
renderCoupon() {
|
|
1276
|
+
if (this._appliedCoupon) {
|
|
1277
|
+
return litHtml.html`
|
|
1278
|
+
<div class="recur-coupon__applied">
|
|
1279
|
+
<div class="recur-coupon__applied-info">
|
|
1280
|
+
${icons.tagApplied}
|
|
1281
|
+
<div class="recur-coupon__applied-details">
|
|
1282
|
+
<div class="recur-coupon__applied-name">
|
|
1283
|
+
${this._appliedCoupon.couponName || this._appliedCoupon.code}
|
|
1284
|
+
</div>
|
|
1285
|
+
${this._appliedCoupon.couponName ? litHtml.html`
|
|
1286
|
+
<div class="recur-coupon__applied-code">代碼:${this._appliedCoupon.code}</div>
|
|
1287
|
+
` : litHtml.nothing}
|
|
1513
1288
|
</div>
|
|
1514
|
-
` : ""}
|
|
1515
|
-
<div class="recur-info-row">
|
|
1516
|
-
<span class="recur-info-label">\u96FB\u5B50\u90F5\u4EF6</span>
|
|
1517
|
-
<span class="recur-info-value">${customerEmail}</span>
|
|
1518
1289
|
</div>
|
|
1290
|
+
<span class="recur-coupon__applied-amount">
|
|
1291
|
+
-NT$ ${this._appliedCoupon.discountAmount.toLocaleString()}
|
|
1292
|
+
</span>
|
|
1293
|
+
<button
|
|
1294
|
+
type="button"
|
|
1295
|
+
class="recur-coupon__remove"
|
|
1296
|
+
?disabled=${this._couponLoading}
|
|
1297
|
+
@click=${() => this.removeCoupon()}
|
|
1298
|
+
>
|
|
1299
|
+
${this._couponLoading ? icons.spinner : icons.close}
|
|
1300
|
+
</button>
|
|
1519
1301
|
</div>
|
|
1520
1302
|
`;
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
}
|
|
1557
|
-
</style>
|
|
1558
|
-
|
|
1559
|
-
<div class="recur-form-group">
|
|
1560
|
-
<label class="recur-form-label" for="${this.containerId}-email">Email</label>
|
|
1561
|
-
<input
|
|
1562
|
-
type="email"
|
|
1563
|
-
id="${this.containerId}-email"
|
|
1564
|
-
class="recur-form-input"
|
|
1565
|
-
placeholder="your@email.com"
|
|
1566
|
-
required
|
|
1567
|
-
/>
|
|
1303
|
+
}
|
|
1304
|
+
if (this._showCouponInput) {
|
|
1305
|
+
return litHtml.html`
|
|
1306
|
+
<div style="width: 100%;">
|
|
1307
|
+
<div class="recur-coupon__input-row">
|
|
1308
|
+
<input
|
|
1309
|
+
type="text"
|
|
1310
|
+
class="recur-coupon__input"
|
|
1311
|
+
id="${this.containerId}-coupon-input"
|
|
1312
|
+
placeholder="輸入優惠碼"
|
|
1313
|
+
.value=${this._couponCode}
|
|
1314
|
+
?disabled=${this._couponLoading}
|
|
1315
|
+
@input=${(e) => this.handleCouponInputChange(e)}
|
|
1316
|
+
@keydown=${(e) => this.handleCouponKeydown(e)}
|
|
1317
|
+
/>
|
|
1318
|
+
<button
|
|
1319
|
+
type="button"
|
|
1320
|
+
class="recur-coupon__btn recur-coupon__btn--apply"
|
|
1321
|
+
?disabled=${this._couponLoading || !this._couponCode.trim()}
|
|
1322
|
+
@click=${() => this.applyCoupon()}
|
|
1323
|
+
>
|
|
1324
|
+
${this._couponLoading ? icons.spinner : "\u5957\u7528"}
|
|
1325
|
+
</button>
|
|
1326
|
+
<button
|
|
1327
|
+
type="button"
|
|
1328
|
+
class="recur-coupon__btn recur-coupon__btn--cancel"
|
|
1329
|
+
?disabled=${this._couponLoading}
|
|
1330
|
+
@click=${() => this.cancelCouponInput()}
|
|
1331
|
+
>
|
|
1332
|
+
取消
|
|
1333
|
+
</button>
|
|
1334
|
+
</div>
|
|
1335
|
+
${this._couponError ? litHtml.html`
|
|
1336
|
+
<div class="recur-coupon__error">${this._couponError}</div>
|
|
1337
|
+
` : litHtml.nothing}
|
|
1568
1338
|
</div>
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1339
|
+
`;
|
|
1340
|
+
}
|
|
1341
|
+
return litHtml.html`
|
|
1342
|
+
<button
|
|
1343
|
+
type="button"
|
|
1344
|
+
class="recur-coupon__trigger"
|
|
1345
|
+
@click=${() => this.showCouponInput()}
|
|
1346
|
+
>
|
|
1347
|
+
${icons.tag}
|
|
1348
|
+
有優惠碼?
|
|
1349
|
+
</button>
|
|
1350
|
+
`;
|
|
1351
|
+
}
|
|
1352
|
+
// Coupon event handlers
|
|
1353
|
+
showCouponInput() {
|
|
1354
|
+
this._showCouponInput = true;
|
|
1355
|
+
this._couponError = null;
|
|
1356
|
+
this.updateCouponSectionDOM();
|
|
1357
|
+
requestAnimationFrame(() => {
|
|
1358
|
+
const input = document.getElementById(`${this.containerId}-coupon-input`);
|
|
1359
|
+
input?.focus();
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
cancelCouponInput() {
|
|
1363
|
+
this._showCouponInput = false;
|
|
1364
|
+
this._couponCode = "";
|
|
1365
|
+
this._couponError = null;
|
|
1366
|
+
this.updateCouponSectionDOM();
|
|
1367
|
+
}
|
|
1368
|
+
handleCouponInputChange(e) {
|
|
1369
|
+
this._couponCode = e.target.value.toUpperCase();
|
|
1370
|
+
this._couponError = null;
|
|
1371
|
+
this.updateApplyButtonState();
|
|
1372
|
+
}
|
|
1373
|
+
handleCouponKeydown(e) {
|
|
1374
|
+
if (e.key === "Enter") {
|
|
1375
|
+
e.preventDefault();
|
|
1376
|
+
this.applyCoupon();
|
|
1377
|
+
} else if (e.key === "Escape") {
|
|
1378
|
+
this.cancelCouponInput();
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
updateApplyButtonState() {
|
|
1382
|
+
const btn = this.querySelector(".recur-coupon__btn--apply");
|
|
1383
|
+
if (btn) {
|
|
1384
|
+
btn.disabled = this._couponLoading || !this._couponCode.trim();
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
// Direct DOM manipulation for coupon section updates (avoids lit-html tracking issues)
|
|
1388
|
+
updateCouponSectionDOM() {
|
|
1389
|
+
const container = document.getElementById(`${this.containerId}-coupon`);
|
|
1390
|
+
if (!container) return;
|
|
1391
|
+
if (this._appliedCoupon) {
|
|
1392
|
+
container.innerHTML = this.getCouponAppliedHTML();
|
|
1393
|
+
this.bindCouponAppliedEvents(container);
|
|
1394
|
+
} else if (this._showCouponInput) {
|
|
1395
|
+
container.innerHTML = this.getCouponInputHTML();
|
|
1396
|
+
this.bindCouponInputEvents(container);
|
|
1397
|
+
} else {
|
|
1398
|
+
container.innerHTML = this.getCouponTriggerHTML();
|
|
1399
|
+
this.bindCouponTriggerEvents(container);
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
getCouponTriggerHTML() {
|
|
1403
|
+
return `
|
|
1404
|
+
<button type="button" class="recur-coupon__trigger">
|
|
1405
|
+
<svg class="recur-coupon__trigger-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1406
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
|
|
1407
|
+
</svg>
|
|
1408
|
+
\u6709\u512A\u60E0\u78BC\uFF1F
|
|
1409
|
+
</button>
|
|
1410
|
+
`;
|
|
1411
|
+
}
|
|
1412
|
+
getCouponInputHTML() {
|
|
1413
|
+
const errorHTML = this._couponError ? `<div class="recur-coupon__error">${this._couponError}</div>` : "";
|
|
1414
|
+
return `
|
|
1415
|
+
<div style="width: 100%;">
|
|
1416
|
+
<div class="recur-coupon__input-row">
|
|
1572
1417
|
<input
|
|
1573
1418
|
type="text"
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
placeholder="\
|
|
1577
|
-
value="${
|
|
1578
|
-
|
|
1419
|
+
class="recur-coupon__input"
|
|
1420
|
+
id="${this.containerId}-coupon-input"
|
|
1421
|
+
placeholder="\u8F38\u5165\u512A\u60E0\u78BC"
|
|
1422
|
+
value="${this._couponCode}"
|
|
1423
|
+
${this._couponLoading ? "disabled" : ""}
|
|
1579
1424
|
/>
|
|
1425
|
+
<button
|
|
1426
|
+
type="button"
|
|
1427
|
+
class="recur-coupon__btn recur-coupon__btn--apply"
|
|
1428
|
+
${this._couponLoading || !this._couponCode.trim() ? "disabled" : ""}
|
|
1429
|
+
>
|
|
1430
|
+
${this._couponLoading ? '<span class="recur-coupon__spinner"></span>' : "\u5957\u7528"}
|
|
1431
|
+
</button>
|
|
1432
|
+
<button
|
|
1433
|
+
type="button"
|
|
1434
|
+
class="recur-coupon__btn recur-coupon__btn--cancel"
|
|
1435
|
+
${this._couponLoading ? "disabled" : ""}
|
|
1436
|
+
>
|
|
1437
|
+
\u53D6\u6D88
|
|
1438
|
+
</button>
|
|
1580
1439
|
</div>
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1440
|
+
${errorHTML}
|
|
1441
|
+
</div>
|
|
1442
|
+
`;
|
|
1584
1443
|
}
|
|
1585
|
-
|
|
1586
|
-
const
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
<
|
|
1590
|
-
|
|
1591
|
-
|
|
1444
|
+
getCouponAppliedHTML() {
|
|
1445
|
+
const coupon = this._appliedCoupon;
|
|
1446
|
+
const codeHTML = coupon.couponName ? `<div class="recur-coupon__applied-code">\u4EE3\u78BC\uFF1A${coupon.code}</div>` : "";
|
|
1447
|
+
return `
|
|
1448
|
+
<div class="recur-coupon__applied">
|
|
1449
|
+
<div class="recur-coupon__applied-info">
|
|
1450
|
+
<svg class="recur-coupon__applied-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1451
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
|
|
1452
|
+
</svg>
|
|
1453
|
+
<div class="recur-coupon__applied-details">
|
|
1454
|
+
<div class="recur-coupon__applied-name">${coupon.couponName || coupon.code}</div>
|
|
1455
|
+
${codeHTML}
|
|
1456
|
+
</div>
|
|
1457
|
+
</div>
|
|
1458
|
+
<span class="recur-coupon__applied-amount">-NT$ ${coupon.discountAmount.toLocaleString()}</span>
|
|
1459
|
+
<button type="button" class="recur-coupon__remove" ${this._couponLoading ? "disabled" : ""}>
|
|
1460
|
+
${this._couponLoading ? '<span class="recur-coupon__spinner"></span>' : '<svg class="recur-coupon__remove-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /></svg>'}
|
|
1461
|
+
</button>
|
|
1462
|
+
</div>
|
|
1463
|
+
`;
|
|
1464
|
+
}
|
|
1465
|
+
bindCouponTriggerEvents(container) {
|
|
1466
|
+
const btn = container.querySelector(".recur-coupon__trigger");
|
|
1467
|
+
btn?.addEventListener("click", () => this.showCouponInput());
|
|
1468
|
+
}
|
|
1469
|
+
bindCouponInputEvents(container) {
|
|
1470
|
+
const input = container.querySelector(".recur-coupon__input");
|
|
1471
|
+
const applyBtn = container.querySelector(".recur-coupon__btn--apply");
|
|
1472
|
+
const cancelBtn = container.querySelector(".recur-coupon__btn--cancel");
|
|
1473
|
+
input?.addEventListener("input", (e) => this.handleCouponInputChange(e));
|
|
1474
|
+
input?.addEventListener("keydown", (e) => this.handleCouponKeydown(e));
|
|
1475
|
+
applyBtn?.addEventListener("click", () => this.applyCoupon());
|
|
1476
|
+
cancelBtn?.addEventListener("click", () => this.cancelCouponInput());
|
|
1477
|
+
}
|
|
1478
|
+
bindCouponAppliedEvents(container) {
|
|
1479
|
+
const removeBtn = container.querySelector(".recur-coupon__remove");
|
|
1480
|
+
removeBtn?.addEventListener("click", () => this.removeCoupon());
|
|
1481
|
+
}
|
|
1482
|
+
updateOrderSummaryDOM() {
|
|
1483
|
+
const summaryContainer = document.getElementById(`${this.containerId}-order-summary`);
|
|
1484
|
+
if (!summaryContainer) return;
|
|
1485
|
+
const amount = Number(this.getAttribute("amount") || 0);
|
|
1486
|
+
const discountAmount = this._appliedCoupon?.discountAmount || 0;
|
|
1487
|
+
const finalAmount = amount - discountAmount;
|
|
1488
|
+
let discountRow = summaryContainer.querySelector(".recur-order-summary__row--discount");
|
|
1489
|
+
const totalRow = summaryContainer.querySelector(".recur-order-summary__row--total");
|
|
1490
|
+
if (discountAmount > 0) {
|
|
1491
|
+
if (!discountRow && totalRow) {
|
|
1492
|
+
const subtotalHTML = `
|
|
1493
|
+
<div class="recur-order-summary__row">
|
|
1494
|
+
<span class="recur-order-summary__label">\u5C0F\u8A08</span>
|
|
1495
|
+
<span class="recur-order-summary__value">NT$ ${amount.toLocaleString()}</span>
|
|
1496
|
+
</div>
|
|
1497
|
+
`;
|
|
1498
|
+
const discountHTML = `
|
|
1499
|
+
<div class="recur-order-summary__row recur-order-summary__row--discount">
|
|
1500
|
+
<span class="recur-order-summary__label">\u6298\u6263</span>
|
|
1501
|
+
<span class="recur-order-summary__value">-NT$ ${discountAmount.toLocaleString()}</span>
|
|
1502
|
+
</div>
|
|
1503
|
+
`;
|
|
1504
|
+
totalRow.insertAdjacentHTML("beforebegin", subtotalHTML + discountHTML);
|
|
1505
|
+
}
|
|
1506
|
+
} else {
|
|
1507
|
+
const subtotalRow = summaryContainer.querySelector(".recur-order-summary__row:not(.recur-order-summary__row--total):last-of-type");
|
|
1508
|
+
discountRow?.remove();
|
|
1509
|
+
if (subtotalRow?.querySelector(".recur-order-summary__label")?.textContent === "\u5C0F\u8A08") {
|
|
1510
|
+
subtotalRow.remove();
|
|
1511
|
+
}
|
|
1592
1512
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
font-size: 14px;
|
|
1597
|
-
font-weight: 500;
|
|
1598
|
-
color: #2d3748;
|
|
1599
|
-
margin-bottom: 6px;
|
|
1513
|
+
const totalValue = totalRow?.querySelector(".recur-order-summary__total");
|
|
1514
|
+
if (totalValue) {
|
|
1515
|
+
totalValue.textContent = `NT$ ${finalAmount.toLocaleString()}`;
|
|
1600
1516
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1517
|
+
this.updateCouponSectionDOM();
|
|
1518
|
+
}
|
|
1519
|
+
// ============================================
|
|
1520
|
+
// Coupon API Methods
|
|
1521
|
+
// ============================================
|
|
1522
|
+
async applyCoupon() {
|
|
1523
|
+
const code = this._couponCode.trim();
|
|
1524
|
+
if (!code) {
|
|
1525
|
+
this._couponError = "\u8ACB\u8F38\u5165\u512A\u60E0\u78BC";
|
|
1526
|
+
this.updateCouponSectionDOM();
|
|
1527
|
+
return;
|
|
1610
1528
|
}
|
|
1611
|
-
|
|
1612
|
-
.
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
box-sizing: border-box;
|
|
1529
|
+
const checkoutId = this.getAttribute("checkout-id");
|
|
1530
|
+
const apiBaseUrl = this.getAttribute("api-base-url") || "";
|
|
1531
|
+
if (!checkoutId) {
|
|
1532
|
+
this._couponError = "\u7121\u6CD5\u5957\u7528\u512A\u60E0\u78BC";
|
|
1533
|
+
this.updateCouponSectionDOM();
|
|
1534
|
+
return;
|
|
1618
1535
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
.
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1536
|
+
this._couponLoading = true;
|
|
1537
|
+
this._couponError = null;
|
|
1538
|
+
this.updateCouponSectionDOM();
|
|
1539
|
+
try {
|
|
1540
|
+
const response = await fetch(`${apiBaseUrl}/api/checkout/${checkoutId}/coupon`, {
|
|
1541
|
+
method: "POST",
|
|
1542
|
+
headers: { "Content-Type": "application/json" },
|
|
1543
|
+
body: JSON.stringify({ code })
|
|
1544
|
+
});
|
|
1545
|
+
const data = await response.json();
|
|
1546
|
+
if (!response.ok) {
|
|
1547
|
+
this._couponError = data.error?.message || "\u512A\u60E0\u78BC\u7121\u6548";
|
|
1548
|
+
this._couponLoading = false;
|
|
1549
|
+
this.updateCouponSectionDOM();
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1552
|
+
this._appliedCoupon = {
|
|
1553
|
+
code: data.discount.code,
|
|
1554
|
+
couponName: data.discount.couponName,
|
|
1555
|
+
discountType: data.discount.discountType,
|
|
1556
|
+
discountAmount: data.discount.discountAmount,
|
|
1557
|
+
duration: data.discount.duration,
|
|
1558
|
+
durationMonths: data.discount.durationMonths,
|
|
1559
|
+
bonusTrialDays: data.discount.bonusTrialDays,
|
|
1560
|
+
bonusMonths: data.discount.bonusMonths
|
|
1561
|
+
};
|
|
1562
|
+
this._showCouponInput = false;
|
|
1563
|
+
this._couponCode = "";
|
|
1564
|
+
this._couponLoading = false;
|
|
1565
|
+
this.updateOrderSummaryDOM();
|
|
1566
|
+
this.dispatchEvent(new CustomEvent("coupon-applied", {
|
|
1567
|
+
detail: { coupon: this._appliedCoupon },
|
|
1568
|
+
bubbles: true,
|
|
1569
|
+
composed: true
|
|
1570
|
+
}));
|
|
1571
|
+
} catch (err) {
|
|
1572
|
+
this._couponError = "\u7DB2\u8DEF\u932F\u8AA4\uFF0C\u8ACB\u7A0D\u5F8C\u518D\u8A66";
|
|
1573
|
+
this._couponLoading = false;
|
|
1574
|
+
this.updateCouponSectionDOM();
|
|
1625
1575
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
.
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
height: 36px;
|
|
1633
|
-
width: 100%;
|
|
1634
|
-
background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);
|
|
1635
|
-
background-size: 200% 100%;
|
|
1636
|
-
animation: recur-skeleton-loading 1.5s ease-in-out infinite;
|
|
1637
|
-
border-radius: 4px;
|
|
1638
|
-
z-index: 1;
|
|
1639
|
-
pointer-events: none;
|
|
1576
|
+
}
|
|
1577
|
+
async removeCoupon() {
|
|
1578
|
+
const checkoutId = this.getAttribute("checkout-id");
|
|
1579
|
+
const apiBaseUrl = this.getAttribute("api-base-url") || "";
|
|
1580
|
+
if (!checkoutId) {
|
|
1581
|
+
return;
|
|
1640
1582
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1583
|
+
this._couponLoading = true;
|
|
1584
|
+
this.updateCouponSectionDOM();
|
|
1585
|
+
try {
|
|
1586
|
+
const response = await fetch(`${apiBaseUrl}/api/checkout/${checkoutId}/coupon`, {
|
|
1587
|
+
method: "DELETE"
|
|
1588
|
+
});
|
|
1589
|
+
if (!response.ok) {
|
|
1590
|
+
const data = await response.json();
|
|
1591
|
+
this._couponError = data.error?.message || "\u79FB\u9664\u5931\u6557";
|
|
1592
|
+
this._couponLoading = false;
|
|
1593
|
+
this.updateCouponSectionDOM();
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
const removedCoupon = this._appliedCoupon;
|
|
1597
|
+
this._appliedCoupon = null;
|
|
1598
|
+
this._couponLoading = false;
|
|
1599
|
+
this.updateOrderSummaryDOM();
|
|
1600
|
+
this.dispatchEvent(new CustomEvent("coupon-removed", {
|
|
1601
|
+
detail: { coupon: removedCoupon },
|
|
1602
|
+
bubbles: true,
|
|
1603
|
+
composed: true
|
|
1604
|
+
}));
|
|
1605
|
+
} catch (err) {
|
|
1606
|
+
this._couponError = "\u7DB2\u8DEF\u932F\u8AA4\uFF0C\u8ACB\u7A0D\u5F8C\u518D\u8A66";
|
|
1607
|
+
this._couponLoading = false;
|
|
1608
|
+
this.updateCouponSectionDOM();
|
|
1645
1609
|
}
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Get applied coupon (for external use)
|
|
1613
|
+
*/
|
|
1614
|
+
getAppliedCoupon() {
|
|
1615
|
+
return this._appliedCoupon;
|
|
1616
|
+
}
|
|
1617
|
+
renderCustomerInfo() {
|
|
1618
|
+
const customerName = this.getAttribute("customer-name");
|
|
1619
|
+
const customerEmail = this.getAttribute("customer-email");
|
|
1620
|
+
if (customerEmail) {
|
|
1621
|
+
return litHtml.html`
|
|
1622
|
+
<div class="recur-info-display">
|
|
1623
|
+
${customerName ? litHtml.html`
|
|
1624
|
+
<div class="recur-info-row">
|
|
1625
|
+
<span class="recur-info-label">姓名</span>
|
|
1626
|
+
<span class="recur-info-value">${customerName}</span>
|
|
1627
|
+
</div>
|
|
1628
|
+
` : litHtml.nothing}
|
|
1629
|
+
<div class="recur-info-row">
|
|
1630
|
+
<span class="recur-info-label">電子郵件</span>
|
|
1631
|
+
<span class="recur-info-value">${customerEmail}</span>
|
|
1632
|
+
</div>
|
|
1633
|
+
</div>
|
|
1634
|
+
`;
|
|
1650
1635
|
}
|
|
1651
|
-
|
|
1636
|
+
return litHtml.html`
|
|
1637
|
+
<div class="recur-form-group">
|
|
1638
|
+
<label class="recur-form-label" for="${this.containerId}-email">Email</label>
|
|
1639
|
+
<input
|
|
1640
|
+
type="email"
|
|
1641
|
+
id="${this.containerId}-email"
|
|
1642
|
+
class="recur-form-input"
|
|
1643
|
+
placeholder="your@email.com"
|
|
1644
|
+
required
|
|
1645
|
+
/>
|
|
1646
|
+
</div>
|
|
1652
1647
|
|
|
1648
|
+
<div class="recur-form-group">
|
|
1649
|
+
<label class="recur-form-label" for="${this.containerId}-name">姓名</label>
|
|
1650
|
+
<input
|
|
1651
|
+
type="text"
|
|
1652
|
+
id="${this.containerId}-name"
|
|
1653
|
+
class="recur-form-input"
|
|
1654
|
+
placeholder="王小明"
|
|
1655
|
+
.value=${customerName || ""}
|
|
1656
|
+
required
|
|
1657
|
+
/>
|
|
1658
|
+
</div>
|
|
1659
|
+
`;
|
|
1660
|
+
}
|
|
1661
|
+
renderCardFields() {
|
|
1662
|
+
return litHtml.html`
|
|
1653
1663
|
<div class="recur-card-field">
|
|
1654
|
-
<label class="recur-card-field-label"
|
|
1664
|
+
<label class="recur-card-field-label">卡號</label>
|
|
1655
1665
|
<div class="recur-card-field-container" id="${this.containerId}-card-no-wrapper">
|
|
1656
|
-
<!-- Skeleton shown until PAYUNi iframe loads -->
|
|
1657
1666
|
<div class="recur-card-skeleton" id="${this.containerId}-card-no-skeleton"></div>
|
|
1658
|
-
<!-- PAYUNi \u6703\u5728\u9019\u88E1\u6CE8\u5165 iframe -->
|
|
1659
1667
|
<div id="${this.containerId}-card-no" class="recur-payuni-iframe"></div>
|
|
1660
1668
|
</div>
|
|
1661
1669
|
</div>
|
|
1662
1670
|
|
|
1663
1671
|
<div class="recur-card-row">
|
|
1664
1672
|
<div class="recur-card-field">
|
|
1665
|
-
<label class="recur-card-field-label"
|
|
1673
|
+
<label class="recur-card-field-label">有效期限</label>
|
|
1666
1674
|
<div class="recur-card-field-container" id="${this.containerId}-card-exp-wrapper">
|
|
1667
1675
|
<div class="recur-card-skeleton" id="${this.containerId}-card-exp-skeleton"></div>
|
|
1668
1676
|
<div id="${this.containerId}-card-exp" class="recur-payuni-iframe"></div>
|
|
@@ -1670,7 +1678,7 @@ var init_payment_form = __esm({
|
|
|
1670
1678
|
</div>
|
|
1671
1679
|
|
|
1672
1680
|
<div class="recur-card-field">
|
|
1673
|
-
<label class="recur-card-field-label"
|
|
1681
|
+
<label class="recur-card-field-label">安全碼</label>
|
|
1674
1682
|
<div class="recur-card-field-container" id="${this.containerId}-card-cvc-wrapper">
|
|
1675
1683
|
<div class="recur-card-skeleton" id="${this.containerId}-card-cvc-skeleton"></div>
|
|
1676
1684
|
<div id="${this.containerId}-card-cvc" class="recur-payuni-iframe"></div>
|
|
@@ -1678,11 +1686,7 @@ var init_payment_form = __esm({
|
|
|
1678
1686
|
</div>
|
|
1679
1687
|
</div>
|
|
1680
1688
|
`;
|
|
1681
|
-
return section;
|
|
1682
1689
|
}
|
|
1683
|
-
/**
|
|
1684
|
-
* Hide card field skeletons after PAYUNi iframes are loaded
|
|
1685
|
-
*/
|
|
1686
1690
|
hideCardSkeletons() {
|
|
1687
1691
|
const skeletonIds = [
|
|
1688
1692
|
`${this.containerId}-card-no-skeleton`,
|
|
@@ -1696,71 +1700,21 @@ var init_payment_form = __esm({
|
|
|
1696
1700
|
}
|
|
1697
1701
|
});
|
|
1698
1702
|
}
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
section.className = "actions-section";
|
|
1702
|
-
section.innerHTML = `
|
|
1703
|
-
<style>
|
|
1704
|
-
.recur-submit-button {
|
|
1705
|
-
width: 100%;
|
|
1706
|
-
padding: 14px 20px;
|
|
1707
|
-
font-size: 16px;
|
|
1708
|
-
font-weight: 500;
|
|
1709
|
-
color: #ffffff;
|
|
1710
|
-
background: #18181b;
|
|
1711
|
-
border: none;
|
|
1712
|
-
border-radius: 6px;
|
|
1713
|
-
cursor: pointer;
|
|
1714
|
-
transition: background-color 0.2s;
|
|
1715
|
-
display: flex;
|
|
1716
|
-
align-items: center;
|
|
1717
|
-
justify-content: center;
|
|
1718
|
-
gap: 8px;
|
|
1719
|
-
box-sizing: border-box;
|
|
1720
|
-
}
|
|
1721
|
-
|
|
1722
|
-
.recur-submit-button:hover:not(:disabled) {
|
|
1723
|
-
background: #27272a;
|
|
1724
|
-
}
|
|
1725
|
-
|
|
1726
|
-
.recur-submit-button:disabled {
|
|
1727
|
-
opacity: 0.6;
|
|
1728
|
-
cursor: not-allowed;
|
|
1729
|
-
}
|
|
1730
|
-
|
|
1731
|
-
.recur-submit-button.loading {
|
|
1732
|
-
cursor: wait;
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
|
-
.recur-loading-spinner {
|
|
1736
|
-
width: 16px;
|
|
1737
|
-
height: 16px;
|
|
1738
|
-
border: 2px solid currentColor;
|
|
1739
|
-
border-top-color: transparent;
|
|
1740
|
-
border-radius: 50%;
|
|
1741
|
-
animation: recur-spin 0.6s linear infinite;
|
|
1742
|
-
}
|
|
1743
|
-
|
|
1744
|
-
@keyframes recur-spin {
|
|
1745
|
-
to { transform: rotate(360deg); }
|
|
1746
|
-
}
|
|
1747
|
-
</style>
|
|
1748
|
-
|
|
1703
|
+
renderActions() {
|
|
1704
|
+
return litHtml.html`
|
|
1749
1705
|
<button
|
|
1750
1706
|
type="submit"
|
|
1751
1707
|
id="${this.containerId}-submit-btn"
|
|
1752
1708
|
class="recur-submit-button"
|
|
1753
1709
|
disabled
|
|
1754
1710
|
>
|
|
1755
|
-
<span id="${this.containerId}-submit-text"
|
|
1711
|
+
<span id="${this.containerId}-submit-text">確認付款</span>
|
|
1756
1712
|
</button>
|
|
1757
1713
|
`;
|
|
1758
|
-
return section;
|
|
1759
1714
|
}
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
*/
|
|
1715
|
+
// ============================================
|
|
1716
|
+
// PAYUNi Integration
|
|
1717
|
+
// ============================================
|
|
1764
1718
|
async initializePayment(sdkToken, environment) {
|
|
1765
1719
|
if (this._initializationAborted) {
|
|
1766
1720
|
console.log("[PaymentForm] Initialization aborted before start");
|
|
@@ -1794,7 +1748,6 @@ var init_payment_form = __esm({
|
|
|
1794
1748
|
const paymentSession = window.UniPayment.createSession(sdkToken, {
|
|
1795
1749
|
env: environment === "SANDBOX" ? "S" : "P",
|
|
1796
1750
|
elements: {
|
|
1797
|
-
// 這些 ID 在 Light DOM 中,document.getElementById 可以找到
|
|
1798
1751
|
CardNo: `${this.containerId}-card-no`,
|
|
1799
1752
|
CardExp: `${this.containerId}-card-exp`,
|
|
1800
1753
|
CardCvc: `${this.containerId}-card-cvc`
|
|
@@ -1883,17 +1836,17 @@ var init_payment_form = __esm({
|
|
|
1883
1836
|
detail: {
|
|
1884
1837
|
customerEmail: email,
|
|
1885
1838
|
customerName: name,
|
|
1886
|
-
paymentSession: this._paymentSession
|
|
1839
|
+
paymentSession: this._paymentSession,
|
|
1840
|
+
appliedCoupon: this._appliedCoupon
|
|
1887
1841
|
},
|
|
1888
1842
|
bubbles: true,
|
|
1889
1843
|
composed: true
|
|
1890
|
-
// 讓事件可以穿透 Shadow DOM
|
|
1891
1844
|
}));
|
|
1892
1845
|
});
|
|
1893
1846
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1847
|
+
// ============================================
|
|
1848
|
+
// UI Helpers
|
|
1849
|
+
// ============================================
|
|
1897
1850
|
setButtonLoading(loading) {
|
|
1898
1851
|
const submitBtn = document.getElementById(`${this.containerId}-submit-btn`);
|
|
1899
1852
|
if (!submitBtn) return;
|
|
@@ -1910,16 +1863,9 @@ var init_payment_form = __esm({
|
|
|
1910
1863
|
submitBtn.innerHTML = '<span id="' + this.containerId + '-submit-text">\u78BA\u8A8D\u4ED8\u6B3E</span>';
|
|
1911
1864
|
}
|
|
1912
1865
|
}
|
|
1913
|
-
/**
|
|
1914
|
-
* Reset button to normal state (call this when payment completes or fails)
|
|
1915
|
-
*/
|
|
1916
1866
|
resetButton() {
|
|
1917
1867
|
this.setButtonLoading(false);
|
|
1918
1868
|
}
|
|
1919
|
-
/**
|
|
1920
|
-
* Set verifying state (for 3D Secure verification)
|
|
1921
|
-
* Shows a "verifying" message while polling for 3D result
|
|
1922
|
-
*/
|
|
1923
1869
|
setVerifying(verifying) {
|
|
1924
1870
|
const submitBtn = document.getElementById(`${this.containerId}-submit-btn`);
|
|
1925
1871
|
if (!submitBtn) return;
|
|
@@ -1934,9 +1880,6 @@ var init_payment_form = __esm({
|
|
|
1934
1880
|
this.setButtonLoading(false);
|
|
1935
1881
|
}
|
|
1936
1882
|
}
|
|
1937
|
-
/**
|
|
1938
|
-
* Show error message using RecurErrorDisplay component
|
|
1939
|
-
*/
|
|
1940
1883
|
showError(message) {
|
|
1941
1884
|
let errorContainer = this.querySelector(".recur-sdk__error-container");
|
|
1942
1885
|
if (!errorContainer) {
|
|
@@ -1952,18 +1895,12 @@ var init_payment_form = __esm({
|
|
|
1952
1895
|
errorContainer.appendChild(errorDisplay);
|
|
1953
1896
|
errorDisplay.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
1954
1897
|
}
|
|
1955
|
-
/**
|
|
1956
|
-
* Clear any displayed errors
|
|
1957
|
-
*/
|
|
1958
1898
|
clearError() {
|
|
1959
1899
|
const errorContainer = this.querySelector(".recur-sdk__error-container");
|
|
1960
1900
|
if (errorContainer) {
|
|
1961
1901
|
errorContainer.innerHTML = "";
|
|
1962
1902
|
}
|
|
1963
1903
|
}
|
|
1964
|
-
/**
|
|
1965
|
-
* 等待組件完全連接到 DOM
|
|
1966
|
-
*/
|
|
1967
1904
|
updateComplete() {
|
|
1968
1905
|
return new Promise((resolve) => {
|
|
1969
1906
|
if (this.isConnected) {
|
|
@@ -1979,18 +1916,12 @@ var init_payment_form = __esm({
|
|
|
1979
1916
|
}
|
|
1980
1917
|
});
|
|
1981
1918
|
}
|
|
1982
|
-
/**
|
|
1983
|
-
* 獲取表單數據
|
|
1984
|
-
*/
|
|
1985
1919
|
getFormData() {
|
|
1986
1920
|
return {
|
|
1987
1921
|
email: document.getElementById(`${this.containerId}-email`)?.value,
|
|
1988
1922
|
name: document.getElementById(`${this.containerId}-name`)?.value
|
|
1989
1923
|
};
|
|
1990
1924
|
}
|
|
1991
|
-
/**
|
|
1992
|
-
* 設置表單數據
|
|
1993
|
-
*/
|
|
1994
1925
|
setFormData(data) {
|
|
1995
1926
|
if (data.email) {
|
|
1996
1927
|
const emailInput = document.getElementById(`${this.containerId}-email`);
|
|
@@ -2544,7 +2475,7 @@ async function registerComponents() {
|
|
|
2544
2475
|
Promise.resolve().then(() => (init_success_message(), success_message_exports)),
|
|
2545
2476
|
Promise.resolve().then(() => (init_error_display(), error_display_exports)),
|
|
2546
2477
|
Promise.resolve().then(() => (init_skeleton_loader(), skeleton_loader_exports)),
|
|
2547
|
-
Promise.resolve().then(() => (
|
|
2478
|
+
Promise.resolve().then(() => (init_payment_form_skeleton2(), payment_form_skeleton_exports)),
|
|
2548
2479
|
Promise.resolve().then(() => (init_toast(), toast_exports)),
|
|
2549
2480
|
Promise.resolve().then(() => (init_payment_form(), payment_form_exports)),
|
|
2550
2481
|
Promise.resolve().then(() => (init_checkout_button(), checkout_button_exports)),
|
|
@@ -2634,7 +2565,7 @@ function toCamelCase(obj) {
|
|
|
2634
2565
|
|
|
2635
2566
|
// package.json
|
|
2636
2567
|
var package_default = {
|
|
2637
|
-
version: "0.9.
|
|
2568
|
+
version: "0.9.8"};
|
|
2638
2569
|
var SDK_VERSION = package_default.version;
|
|
2639
2570
|
var SDK_TYPE = "react";
|
|
2640
2571
|
var RecurContext = React.createContext(null);
|
|
@@ -2814,15 +2745,6 @@ function RecurProvider({ children, config: initialConfig = {} }) {
|
|
|
2814
2745
|
document.body.appendChild(dialog);
|
|
2815
2746
|
dialog.showModal();
|
|
2816
2747
|
lockBodyScroll();
|
|
2817
|
-
dialog.addEventListener("click", (e) => {
|
|
2818
|
-
const rect = dialog.getBoundingClientRect();
|
|
2819
|
-
const isInDialog = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
|
|
2820
|
-
if (!isInDialog) {
|
|
2821
|
-
closeDialog();
|
|
2822
|
-
setIsCheckingOut(false);
|
|
2823
|
-
options.onPaymentCancel?.();
|
|
2824
|
-
}
|
|
2825
|
-
});
|
|
2826
2748
|
dialog.addEventListener("cancel", (e) => {
|
|
2827
2749
|
e.preventDefault();
|
|
2828
2750
|
closeDialog();
|