recur-tw 0.3.3 → 0.3.5

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 CHANGED
@@ -643,21 +643,36 @@ var init_payment_form_skeleton = __esm({
643
643
  margin-bottom: 24px;
644
644
  }
645
645
 
646
+ .form-title {
647
+ font-size: 20px;
648
+ font-weight: 600;
649
+ color: #1a202c;
650
+ margin: 0 0 4px 0;
651
+ }
652
+
653
+ .form-subtitle {
654
+ font-size: 14px;
655
+ color: #718096;
656
+ margin: 0;
657
+ }
658
+
646
659
  .form-section {
647
660
  margin-bottom: 24px;
648
661
  }
649
662
 
650
663
  .section-title {
651
- margin: 0 0 12px 0;
652
- font-size: 16px;
664
+ font-size: 14px;
653
665
  font-weight: 600;
654
666
  color: #2d3748;
667
+ margin: 0 0 12px 0;
655
668
  }
656
669
 
657
670
  .label {
671
+ display: block;
658
672
  font-size: 14px;
659
- color: #4a5568;
660
- margin-bottom: 4px;
673
+ font-weight: 500;
674
+ color: #2d3748;
675
+ margin-bottom: 6px;
661
676
  }
662
677
 
663
678
  /* Skeleton base styles */
@@ -665,7 +680,7 @@ var init_payment_form_skeleton = __esm({
665
680
  background: linear-gradient(
666
681
  90deg,
667
682
  #f0f0f0 0%,
668
- #f8f8f8 50%,
683
+ #e8e8e8 50%,
669
684
  #f0f0f0 100%
670
685
  );
671
686
  background-size: 200% 100%;
@@ -682,68 +697,109 @@ var init_payment_form_skeleton = __esm({
682
697
  }
683
698
  }
684
699
 
685
- .skeleton-title {
686
- height: 28px;
687
- width: 200px;
700
+ /* Order Summary */
701
+ .order-summary {
702
+ background: #f7fafc;
703
+ border: 1px solid #e2e8f0;
704
+ border-radius: 8px;
705
+ padding: 16px;
706
+ margin-bottom: 24px;
707
+ }
708
+
709
+ .order-summary-title {
710
+ font-size: 14px;
711
+ font-weight: 600;
712
+ color: #2d3748;
713
+ margin: 0 0 12px 0;
714
+ }
715
+
716
+ .order-row {
717
+ display: flex;
718
+ justify-content: space-between;
719
+ align-items: center;
688
720
  margin-bottom: 8px;
689
721
  }
690
722
 
691
- .skeleton-subtitle {
692
- height: 18px;
693
- width: 320px;
723
+ .order-row:last-child {
724
+ margin-bottom: 0;
725
+ padding-top: 12px;
726
+ border-top: 1px solid #e2e8f0;
694
727
  }
695
728
 
696
- .skeleton-order-summary {
697
- padding: 16px;
729
+ .order-label {
730
+ font-size: 14px;
731
+ color: #4a5568;
732
+ }
733
+
734
+ .skeleton-order-value {
735
+ height: 20px;
736
+ width: 80px;
737
+ }
738
+
739
+ .skeleton-order-total {
740
+ height: 26px;
741
+ width: 100px;
742
+ }
743
+
744
+ /* Customer Info Display */
745
+ .customer-info-display {
698
746
  background: #f7fafc;
747
+ border: 1px solid #e2e8f0;
699
748
  border-radius: 6px;
700
- margin-bottom: 24px;
749
+ padding: 12px;
750
+ margin-bottom: 8px;
701
751
  }
702
752
 
703
- .skeleton-order-row {
753
+ .info-row {
704
754
  display: flex;
705
- justify-content: space-between;
706
755
  align-items: center;
707
- margin-bottom: 12px;
756
+ margin-bottom: 6px;
708
757
  }
709
758
 
710
- .skeleton-order-row:last-child {
759
+ .info-row:last-child {
711
760
  margin-bottom: 0;
712
- padding-top: 12px;
713
- border-top: 1px solid #e2e8f0;
714
- font-weight: 600;
715
761
  }
716
762
 
717
- .skeleton-order-value {
763
+ .info-label {
764
+ font-size: 13px;
765
+ color: #718096;
766
+ min-width: 80px;
767
+ }
768
+
769
+ .skeleton-info-value {
718
770
  height: 20px;
719
771
  width: 120px;
720
772
  }
721
773
 
722
- .input-group {
774
+ /* Card Fields */
775
+ .card-field {
723
776
  margin-bottom: 16px;
724
777
  }
725
778
 
726
- .input-group:last-child {
779
+ .card-field:last-child {
727
780
  margin-bottom: 0;
728
781
  }
729
782
 
730
783
  .skeleton-input {
731
- height: 44px;
784
+ height: 36px;
732
785
  width: 100%;
786
+ border-radius: 6px;
733
787
  }
734
788
 
735
- .card-fields-grid {
789
+ .card-row {
736
790
  display: grid;
737
791
  grid-template-columns: 1fr 1fr;
738
792
  gap: 12px;
739
793
  }
740
794
 
795
+ /* Submit Button - matches .recur-submit-button: padding 14px*2 + font 16px * line-height ~1.5 */
741
796
  .skeleton-button {
742
- height: 44px;
797
+ height: 52px;
743
798
  width: 100%;
744
799
  border-radius: 6px;
745
800
  }
746
801
 
802
+ /* Security Note */
747
803
  .security-note {
748
804
  display: flex;
749
805
  align-items: center;
@@ -766,73 +822,67 @@ var init_payment_form_skeleton = __esm({
766
822
  </style>
767
823
 
768
824
  <div class="payment-form-wrapper">
769
- <!-- Header Skeleton -->
825
+ <!-- Header (matches payment-form.ts) -->
770
826
  <div class="form-header">
771
- <div class="skeleton skeleton-title"></div>
772
- <div class="skeleton skeleton-subtitle"></div>
827
+ <h2 class="form-title">\u8A02\u95B1\u4ED8\u6B3E</h2>
828
+ <p class="form-subtitle">\u8ACB\u586B\u5BEB\u4FE1\u7528\u5361\u8CC7\u8A0A\u5B8C\u6210\u8A02\u95B1</p>
773
829
  </div>
774
830
 
775
- <!-- Order Summary - Static labels, skeleton values -->
776
- <div class="skeleton-order-summary">
777
- <h3 class="section-title">\u8A02\u55AE\u6458\u8981</h3>
778
- <div class="skeleton-order-row">
779
- <span class="label">\u65B9\u6848</span>
780
- <div class="skeleton skeleton-order-value"></div>
781
- </div>
782
- <div class="skeleton-order-row">
783
- <span class="label">\u91D1\u984D</span>
831
+ <!-- Order Summary (matches createOrderSummarySection) -->
832
+ <div class="order-summary">
833
+ <h3 class="order-summary-title">\u8A02\u55AE\u6458\u8981</h3>
834
+ <div class="order-row">
835
+ <span class="order-label">\u8A02\u95B1\u65B9\u6848</span>
784
836
  <div class="skeleton skeleton-order-value"></div>
785
837
  </div>
786
- <div class="skeleton-order-row">
787
- <span class="label">\u9031\u671F</span>
838
+ <div class="order-row">
839
+ <span class="order-label">\u8A08\u8CBB\u9031\u671F</span>
788
840
  <div class="skeleton skeleton-order-value"></div>
789
841
  </div>
790
- <div class="skeleton-order-row">
791
- <span class="label">\u7E3D\u8A08</span>
792
- <div class="skeleton skeleton-order-value"></div>
842
+ <div class="order-row">
843
+ <span class="order-label">\u7E3D\u8A08</span>
844
+ <div class="skeleton skeleton-order-total"></div>
793
845
  </div>
794
846
  </div>
795
847
 
796
- <!-- Customer Info Section - Static labels, skeleton inputs -->
848
+ <!-- Customer Info Section (matches createCustomerInfoSection read-only display) -->
797
849
  <div class="form-section">
798
850
  <h3 class="section-title">\u5BA2\u6236\u8CC7\u8A0A</h3>
799
- <div class="input-group">
800
- <div class="label">\u59D3\u540D</div>
801
- <div class="skeleton skeleton-input"></div>
802
- </div>
803
- <div class="input-group">
804
- <div class="label">Email</div>
805
- <div class="skeleton skeleton-input"></div>
806
- </div>
807
- <div class="input-group">
808
- <div class="label">\u96FB\u8A71\uFF08\u9078\u586B\uFF09</div>
809
- <div class="skeleton skeleton-input"></div>
851
+ <div class="customer-info-display">
852
+ <div class="info-row">
853
+ <span class="info-label">\u5BA2\u6236\u59D3\u540D\uFF1A</span>
854
+ <div class="skeleton skeleton-info-value"></div>
855
+ </div>
856
+ <div class="info-row">
857
+ <span class="info-label">\u96FB\u5B50\u90F5\u4EF6\uFF1A</span>
858
+ <div class="skeleton skeleton-info-value" style="width: 160px;"></div>
859
+ </div>
810
860
  </div>
811
861
  </div>
812
862
 
813
- <!-- Card Fields Section - Static labels, skeleton inputs -->
863
+ <!-- Card Fields Section (matches createCardFieldsSection) -->
814
864
  <div class="form-section">
815
865
  <h3 class="section-title">\u4FE1\u7528\u5361\u8CC7\u8A0A</h3>
816
- <div class="input-group">
817
- <div class="label">\u4FE1\u7528\u5361\u865F</div>
866
+ <div class="card-field">
867
+ <label class="label">\u5361\u865F</label>
818
868
  <div class="skeleton skeleton-input"></div>
819
869
  </div>
820
- <div class="card-fields-grid">
821
- <div class="input-group">
822
- <div class="label">\u6709\u6548\u671F\u9650</div>
870
+ <div class="card-row">
871
+ <div class="card-field">
872
+ <label class="label">\u6709\u6548\u671F\u9650</label>
823
873
  <div class="skeleton skeleton-input"></div>
824
874
  </div>
825
- <div class="input-group">
826
- <div class="label">\u5B89\u5168\u78BC</div>
875
+ <div class="card-field">
876
+ <label class="label">\u5B89\u5168\u78BC</label>
827
877
  <div class="skeleton skeleton-input"></div>
828
878
  </div>
829
879
  </div>
830
880
  </div>
831
881
 
832
- <!-- Submit Button Skeleton -->
882
+ <!-- Submit Button -->
833
883
  <div class="skeleton skeleton-button"></div>
834
884
 
835
- <!-- Security Note -->
885
+ <!-- Security Note (matches payment-form.ts) -->
836
886
  <div class="security-note">
837
887
  <svg class="security-icon" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
838
888
  <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" />
@@ -1190,10 +1240,10 @@ var init_payment_form = __esm({
1190
1240
  }
1191
1241
 
1192
1242
  .form-title {
1193
- font-size: 24px;
1243
+ font-size: 20px;
1194
1244
  font-weight: 600;
1195
1245
  color: #1a202c;
1196
- margin: 0 0 8px 0;
1246
+ margin: 0 0 4px 0;
1197
1247
  }
1198
1248
 
1199
1249
  .form-subtitle {
@@ -1241,8 +1291,8 @@ var init_payment_form = __esm({
1241
1291
 
1242
1292
  <div class="payment-form-wrapper">
1243
1293
  <div class="form-header">
1244
- <h2 class="form-title">\u4ED8\u6B3E\u8CC7\u8A0A</h2>
1245
- <p class="form-subtitle">\u8ACB\u586B\u5BEB\u60A8\u7684\u4FE1\u7528\u5361\u8CC7\u8A0A\u4EE5\u5B8C\u6210\u8A02\u95B1</p>
1294
+ <h2 class="form-title">\u8A02\u95B1\u4ED8\u6B3E</h2>
1295
+ <p class="form-subtitle">\u8ACB\u586B\u5BEB\u4FE1\u7528\u5361\u8CC7\u8A0A\u5B8C\u6210\u8A02\u95B1</p>
1246
1296
  </div>
1247
1297
 
1248
1298
  <!-- Slot for order summary (Light DOM) -->
@@ -1375,12 +1425,14 @@ var init_payment_form = __esm({
1375
1425
 
1376
1426
  .order-summary-value {
1377
1427
  font-size: 14px;
1428
+ line-height: 20px;
1378
1429
  font-weight: 500;
1379
1430
  color: #2d3748;
1380
1431
  }
1381
1432
 
1382
1433
  .order-summary-total {
1383
1434
  font-size: 18px;
1435
+ line-height: 26px;
1384
1436
  font-weight: 700;
1385
1437
  color: #1a202c;
1386
1438
  }
@@ -1438,6 +1490,7 @@ var init_payment_form = __esm({
1438
1490
 
1439
1491
  .recur-info-value {
1440
1492
  font-size: 14px;
1493
+ line-height: 20px;
1441
1494
  color: #2d3748;
1442
1495
  font-weight: 500;
1443
1496
  }
@@ -1556,11 +1609,43 @@ var init_payment_form = __esm({
1556
1609
  grid-template-columns: 1fr 1fr;
1557
1610
  gap: 12px;
1558
1611
  }
1612
+
1613
+ /* Container needs relative positioning for skeleton overlay */
1614
+ .recur-card-field-container {
1615
+ position: relative;
1616
+ }
1617
+
1618
+ /* Loading skeleton for card fields - shown until PAYUNi iframe loads */
1619
+ .recur-card-skeleton {
1620
+ position: absolute;
1621
+ top: 0;
1622
+ left: 0;
1623
+ height: 36px;
1624
+ width: 100%;
1625
+ background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);
1626
+ background-size: 200% 100%;
1627
+ animation: recur-skeleton-loading 1.5s ease-in-out infinite;
1628
+ border-radius: 4px;
1629
+ z-index: 1;
1630
+ pointer-events: none;
1631
+ }
1632
+
1633
+ /* Hide skeleton when PAYUNi iframe is ready (has content) */
1634
+ .recur-card-skeleton.hidden {
1635
+ display: none;
1636
+ }
1637
+
1638
+ @keyframes recur-skeleton-loading {
1639
+ 0% { background-position: 200% 0; }
1640
+ 100% { background-position: -200% 0; }
1641
+ }
1559
1642
  </style>
1560
1643
 
1561
1644
  <div class="recur-card-field">
1562
1645
  <label class="recur-card-field-label">\u5361\u865F</label>
1563
1646
  <div class="recur-card-field-container" id="${this.containerId}-card-no-wrapper">
1647
+ <!-- Skeleton shown until PAYUNi iframe loads -->
1648
+ <div class="recur-card-skeleton" id="${this.containerId}-card-no-skeleton"></div>
1564
1649
  <!-- PAYUNi \u6703\u5728\u9019\u88E1\u6CE8\u5165 iframe -->
1565
1650
  <div id="${this.containerId}-card-no" class="recur-payuni-iframe"></div>
1566
1651
  </div>
@@ -1570,6 +1655,7 @@ var init_payment_form = __esm({
1570
1655
  <div class="recur-card-field">
1571
1656
  <label class="recur-card-field-label">\u6709\u6548\u671F\u9650</label>
1572
1657
  <div class="recur-card-field-container" id="${this.containerId}-card-exp-wrapper">
1658
+ <div class="recur-card-skeleton" id="${this.containerId}-card-exp-skeleton"></div>
1573
1659
  <div id="${this.containerId}-card-exp" class="recur-payuni-iframe"></div>
1574
1660
  </div>
1575
1661
  </div>
@@ -1577,6 +1663,7 @@ var init_payment_form = __esm({
1577
1663
  <div class="recur-card-field">
1578
1664
  <label class="recur-card-field-label">\u5B89\u5168\u78BC</label>
1579
1665
  <div class="recur-card-field-container" id="${this.containerId}-card-cvc-wrapper">
1666
+ <div class="recur-card-skeleton" id="${this.containerId}-card-cvc-skeleton"></div>
1580
1667
  <div id="${this.containerId}-card-cvc" class="recur-payuni-iframe"></div>
1581
1668
  </div>
1582
1669
  </div>
@@ -1584,6 +1671,22 @@ var init_payment_form = __esm({
1584
1671
  `;
1585
1672
  return section;
1586
1673
  }
1674
+ /**
1675
+ * Hide card field skeletons after PAYUNi iframes are loaded
1676
+ */
1677
+ hideCardSkeletons() {
1678
+ const skeletonIds = [
1679
+ `${this.containerId}-card-no-skeleton`,
1680
+ `${this.containerId}-card-exp-skeleton`,
1681
+ `${this.containerId}-card-cvc-skeleton`
1682
+ ];
1683
+ skeletonIds.forEach((id) => {
1684
+ const skeleton = document.getElementById(id);
1685
+ if (skeleton) {
1686
+ skeleton.classList.add("hidden");
1687
+ }
1688
+ });
1689
+ }
1587
1690
  createActionsSection() {
1588
1691
  const section = document.createElement("div");
1589
1692
  section.className = "actions-section";
@@ -1708,6 +1811,7 @@ var init_payment_form = __esm({
1708
1811
  this._isInitializing = false;
1709
1812
  return null;
1710
1813
  }
1814
+ this.hideCardSkeletons();
1711
1815
  paymentSession.onUpdate?.((data) => {
1712
1816
  if (this._initializationAborted) {
1713
1817
  console.log("[PaymentForm] Ignoring onUpdate event - component disconnected");
@@ -2283,9 +2387,6 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2283
2387
  modalContent = document.createElement("div");
2284
2388
  modalContent.className = "recur-sdk__modal-content";
2285
2389
  modalContent.style.cssText = `
2286
- background: white;
2287
- padding: 32px;
2288
- border-radius: 12px;
2289
2390
  max-width: 500px;
2290
2391
  width: 90%;
2291
2392
  max-height: 90vh;
@@ -2297,11 +2398,11 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2297
2398
  closeButton.innerHTML = "\u2715";
2298
2399
  closeButton.style.cssText = `
2299
2400
  position: absolute;
2300
- top: 16px;
2301
- right: 16px;
2302
- background: none;
2401
+ top: 12px;
2402
+ right: 12px;
2403
+ background: rgba(0, 0, 0, 0.05);
2303
2404
  border: none;
2304
- font-size: 24px;
2405
+ font-size: 18px;
2305
2406
  cursor: pointer;
2306
2407
  color: #666;
2307
2408
  padding: 0;
@@ -2310,24 +2411,32 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2310
2411
  display: flex;
2311
2412
  align-items: center;
2312
2413
  justify-content: center;
2414
+ border-radius: 50%;
2415
+ z-index: 10;
2416
+ transition: background 0.2s;
2313
2417
  `;
2418
+ closeButton.onmouseover = () => {
2419
+ closeButton.style.background = "rgba(0, 0, 0, 0.1)";
2420
+ };
2421
+ closeButton.onmouseout = () => {
2422
+ closeButton.style.background = "rgba(0, 0, 0, 0.05)";
2423
+ };
2314
2424
  closeButton.onclick = () => {
2315
2425
  modalOverlay?.remove();
2316
2426
  setIsCheckingOut(false);
2317
2427
  options.onPaymentCancel?.();
2318
2428
  };
2319
- const title = document.createElement("h2");
2320
- title.className = "recur-sdk__title";
2321
- title.textContent = "\u8A02\u95B1\u4ED8\u6B3E";
2322
- title.style.cssText = "margin: 0 0 24px 0; font-size: 24px; font-weight: 600;";
2323
2429
  loadingContainer = document.createElement("div");
2324
2430
  loadingContainer.id = "recur-modal-loading";
2325
2431
  loadingContainer.className = "recur-sdk__loading-container";
2326
- loadingContainer.style.cssText = "padding: 0;";
2432
+ loadingContainer.style.cssText = `
2433
+ background: white;
2434
+ border-radius: 12px;
2435
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
2436
+ `;
2327
2437
  const skeleton = document.createElement("recur-payment-form-skeleton");
2328
2438
  loadingContainer.appendChild(skeleton);
2329
2439
  modalContent.appendChild(closeButton);
2330
- modalContent.appendChild(title);
2331
2440
  modalContent.appendChild(loadingContainer);
2332
2441
  modalOverlay.appendChild(modalContent);
2333
2442
  document.body.appendChild(modalOverlay);
package/dist/index.d.cts CHANGED
@@ -414,6 +414,10 @@ declare class RecurPaymentForm extends HTMLElement {
414
414
  private createOrderSummarySection;
415
415
  private createCustomerInfoSection;
416
416
  private createCardFieldsSection;
417
+ /**
418
+ * Hide card field skeletons after PAYUNi iframes are loaded
419
+ */
420
+ private hideCardSkeletons;
417
421
  private createActionsSection;
418
422
  /**
419
423
  * 初始化 PAYUNi SDK
package/dist/index.d.ts CHANGED
@@ -414,6 +414,10 @@ declare class RecurPaymentForm extends HTMLElement {
414
414
  private createOrderSummarySection;
415
415
  private createCustomerInfoSection;
416
416
  private createCardFieldsSection;
417
+ /**
418
+ * Hide card field skeletons after PAYUNi iframes are loaded
419
+ */
420
+ private hideCardSkeletons;
417
421
  private createActionsSection;
418
422
  /**
419
423
  * 初始化 PAYUNi SDK