recur-tw 0.3.4 → 0.3.7

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/recur.umd.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var RecurCheckout=(()=>{var k=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var G=(l,e,t)=>e in l?k(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var m=(l,e)=>()=>(l&&(e=l(l=0)),e);var d=(l,e)=>{for(var t in e)k(l,t,{get:e[t],enumerable:!0})},Q=(l,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of J(e))!Z.call(l,i)&&i!==t&&k(l,i,{get:()=>e[i],enumerable:!(r=W(e,i))||r.enumerable});return l};var ee=l=>Q(k({},"__esModule",{value:!0}),l);var n=(l,e,t)=>G(l,typeof e!="symbol"?e+"":e,t);var U={};d(U,{RecurLoadingSpinner:()=>x});var x,H=m(()=>{"use strict";x=class extends HTMLElement{static get observedAttributes(){return["message","size"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get message(){return this.getAttribute("message")||"\u6B63\u5728\u8655\u7406\u8A02\u95B1..."}get size(){let e=this.getAttribute("size");return e==="small"||e==="large"?e:"medium"}getSizeValue(){return{small:24,medium:40,large:56}[this.size]}render(){let e=this.getSizeValue();this.shadowRoot.innerHTML=`
1
+ "use strict";var RecurCheckout=(()=>{var C=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var de=Object.prototype.hasOwnProperty;var ue=(c,e,t)=>e in c?C(c,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):c[e]=t;var g=(c,e)=>()=>(c&&(e=c(c=0)),e);var h=(c,e)=>{for(var t in e)C(c,t,{get:e[t],enumerable:!0})},me=(c,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of le(e))!de.call(c,i)&&i!==t&&C(c,i,{get:()=>e[i],enumerable:!(r=ce(e,i))||r.enumerable});return c};var pe=c=>me(C({},"__esModule",{value:!0}),c);var a=(c,e,t)=>ue(c,typeof e!="symbol"?e+"":e,t);var B={};h(B,{RecurLoadingSpinner:()=>S});var S,N=g(()=>{"use strict";S=class extends HTMLElement{static get observedAttributes(){return["message","size"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get message(){return this.getAttribute("message")||"\u6B63\u5728\u8655\u7406\u8A02\u95B1..."}get size(){let e=this.getAttribute("size");return e==="small"||e==="large"?e:"medium"}getSizeValue(){return{small:24,medium:40,large:56}[this.size]}render(){let e=this.getSizeValue();this.shadowRoot.innerHTML=`
2
2
  <style>
3
3
  :host {
4
4
  display: block;
@@ -40,7 +40,7 @@
40
40
 
41
41
  <div class="recur-sdk__spinner"></div>
42
42
  ${this.message?`<p class="recur-sdk__loading-text">${this.message}</p>`:""}
43
- `}};typeof window<"u"&&!customElements.get("recur-loading-spinner")&&customElements.define("recur-loading-spinner",x)});var $={};d($,{RecurSuccessMessage:()=>w});var w,A=m(()=>{"use strict";w=class extends HTMLElement{static get observedAttributes(){return["title","message","icon"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get successTitle(){return this.getAttribute("title")||"Subscription Complete!"}get successMessage(){return this.getAttribute("message")||"Thank you for subscribing. Your payment has been processed successfully."}get showIcon(){return this.getAttribute("icon")!=="false"}render(){this.shadowRoot.innerHTML=`
43
+ `}};typeof window<"u"&&!customElements.get("recur-loading-spinner")&&customElements.define("recur-loading-spinner",S)});var K={};h(K,{RecurSuccessMessage:()=>I});var I,O=g(()=>{"use strict";I=class extends HTMLElement{static get observedAttributes(){return["title","message","icon"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get successTitle(){return this.getAttribute("title")||"Subscription Complete!"}get successMessage(){return this.getAttribute("message")||"Thank you for subscribing. Your payment has been processed successfully."}get showIcon(){return this.getAttribute("icon")!=="false"}render(){this.shadowRoot.innerHTML=`
44
44
  <style>
45
45
  :host {
46
46
  display: block;
@@ -121,7 +121,7 @@
121
121
  <p class="recur-sdk__success-message">${this.successMessage}</p>
122
122
  <slot></slot>
123
123
  </div>
124
- `}};typeof window<"u"&&!customElements.get("recur-success-message")&&customElements.define("recur-success-message",w)});var B={};d(B,{RecurErrorDisplay:()=>E});var E,D=m(()=>{"use strict";E=class extends HTMLElement{static get observedAttributes(){return["error","dismissible"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get error(){return this.getAttribute("error")||""}get isDismissible(){return this.getAttribute("dismissible")==="true"}handleDismiss(){this.dispatchEvent(new CustomEvent("dismiss",{bubbles:!0,composed:!0})),this.remove()}render(){if(!this.error){this.shadowRoot.innerHTML="";return}this.shadowRoot.innerHTML=`
124
+ `}};typeof window<"u"&&!customElements.get("recur-success-message")&&customElements.define("recur-success-message",I)});var F={};h(F,{RecurErrorDisplay:()=>T});var T,j=g(()=>{"use strict";T=class extends HTMLElement{static get observedAttributes(){return["error","dismissible"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get error(){return this.getAttribute("error")||""}get isDismissible(){return this.getAttribute("dismissible")==="true"}handleDismiss(){this.dispatchEvent(new CustomEvent("dismiss",{bubbles:!0,composed:!0})),this.remove()}render(){if(!this.error){this.shadowRoot.innerHTML="";return}this.shadowRoot.innerHTML=`
125
125
  <style>
126
126
  :host {
127
127
  display: block;
@@ -211,7 +211,7 @@
211
211
  </button>
212
212
  `:""}
213
213
  </div>
214
- `,this.isDismissible&&this.shadowRoot.querySelector(".recur-sdk__error-dismiss")?.addEventListener("click",()=>this.handleDismiss())}};typeof window<"u"&&!customElements.get("recur-error-display")&&customElements.define("recur-error-display",E)});var N={};d(N,{RecurSkeletonLoader:()=>C});var C,O=m(()=>{"use strict";C=class extends HTMLElement{static get observedAttributes(){return["type"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get type(){let e=this.getAttribute("type");return e==="list"||e==="card"?e:"payment-form"}renderPaymentFormSkeleton(){return`
214
+ `,this.isDismissible&&this.shadowRoot.querySelector(".recur-sdk__error-dismiss")?.addEventListener("click",()=>this.handleDismiss())}};typeof window<"u"&&!customElements.get("recur-error-display")&&customElements.define("recur-error-display",T)});var Y={};h(Y,{RecurSkeletonLoader:()=>R});var R,q=g(()=>{"use strict";R=class extends HTMLElement{static get observedAttributes(){return["type"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get type(){let e=this.getAttribute("type");return e==="list"||e==="card"?e:"payment-form"}renderPaymentFormSkeleton(){return`
215
215
  <div class="skeleton-field">
216
216
  <div class="skeleton-label"></div>
217
217
  <div class="skeleton-input"></div>
@@ -377,7 +377,7 @@
377
377
  </style>
378
378
 
379
379
  ${e}
380
- `}};typeof window<"u"&&!customElements.get("recur-skeleton-loader")&&customElements.define("recur-skeleton-loader",C)});var F={};d(F,{RecurPaymentFormSkeleton:()=>T});var T,j=m(()=>{"use strict";T=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}render(){this.shadowRoot.innerHTML=`
380
+ `}};typeof window<"u"&&!customElements.get("recur-skeleton-loader")&&customElements.define("recur-skeleton-loader",R)});var V={};h(V,{RecurPaymentFormSkeleton:()=>P});var P,X=g(()=>{"use strict";P=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}render(){this.shadowRoot.innerHTML=`
381
381
  <style>
382
382
  :host {
383
383
  display: block;
@@ -397,21 +397,36 @@
397
397
  margin-bottom: 24px;
398
398
  }
399
399
 
400
+ .form-title {
401
+ font-size: 20px;
402
+ font-weight: 600;
403
+ color: #1a202c;
404
+ margin: 0 0 4px 0;
405
+ }
406
+
407
+ .form-subtitle {
408
+ font-size: 14px;
409
+ color: #718096;
410
+ margin: 0;
411
+ }
412
+
400
413
  .form-section {
401
414
  margin-bottom: 24px;
402
415
  }
403
416
 
404
417
  .section-title {
405
- margin: 0 0 12px 0;
406
- font-size: 16px;
418
+ font-size: 14px;
407
419
  font-weight: 600;
408
420
  color: #2d3748;
421
+ margin: 0 0 12px 0;
409
422
  }
410
423
 
411
424
  .label {
425
+ display: block;
412
426
  font-size: 14px;
413
- color: #4a5568;
414
- margin-bottom: 4px;
427
+ font-weight: 500;
428
+ color: #2d3748;
429
+ margin-bottom: 6px;
415
430
  }
416
431
 
417
432
  /* Skeleton base styles */
@@ -419,7 +434,7 @@
419
434
  background: linear-gradient(
420
435
  90deg,
421
436
  #f0f0f0 0%,
422
- #f8f8f8 50%,
437
+ #e8e8e8 50%,
423
438
  #f0f0f0 100%
424
439
  );
425
440
  background-size: 200% 100%;
@@ -436,68 +451,109 @@
436
451
  }
437
452
  }
438
453
 
439
- .skeleton-title {
440
- height: 28px;
441
- width: 200px;
454
+ /* Order Summary */
455
+ .order-summary {
456
+ background: #f7fafc;
457
+ border: 1px solid #e2e8f0;
458
+ border-radius: 8px;
459
+ padding: 16px;
460
+ margin-bottom: 24px;
461
+ }
462
+
463
+ .order-summary-title {
464
+ font-size: 14px;
465
+ font-weight: 600;
466
+ color: #2d3748;
467
+ margin: 0 0 12px 0;
468
+ }
469
+
470
+ .order-row {
471
+ display: flex;
472
+ justify-content: space-between;
473
+ align-items: center;
442
474
  margin-bottom: 8px;
443
475
  }
444
476
 
445
- .skeleton-subtitle {
446
- height: 18px;
447
- width: 320px;
477
+ .order-row:last-child {
478
+ margin-bottom: 0;
479
+ padding-top: 12px;
480
+ border-top: 1px solid #e2e8f0;
448
481
  }
449
482
 
450
- .skeleton-order-summary {
451
- padding: 16px;
483
+ .order-label {
484
+ font-size: 14px;
485
+ color: #4a5568;
486
+ }
487
+
488
+ .skeleton-order-value {
489
+ height: 20px;
490
+ width: 80px;
491
+ }
492
+
493
+ .skeleton-order-total {
494
+ height: 26px;
495
+ width: 100px;
496
+ }
497
+
498
+ /* Customer Info Display */
499
+ .customer-info-display {
452
500
  background: #f7fafc;
501
+ border: 1px solid #e2e8f0;
453
502
  border-radius: 6px;
454
- margin-bottom: 24px;
503
+ padding: 12px;
504
+ margin-bottom: 8px;
455
505
  }
456
506
 
457
- .skeleton-order-row {
507
+ .info-row {
458
508
  display: flex;
459
- justify-content: space-between;
460
509
  align-items: center;
461
- margin-bottom: 12px;
510
+ margin-bottom: 6px;
462
511
  }
463
512
 
464
- .skeleton-order-row:last-child {
513
+ .info-row:last-child {
465
514
  margin-bottom: 0;
466
- padding-top: 12px;
467
- border-top: 1px solid #e2e8f0;
468
- font-weight: 600;
469
515
  }
470
516
 
471
- .skeleton-order-value {
517
+ .info-label {
518
+ font-size: 13px;
519
+ color: #718096;
520
+ min-width: 80px;
521
+ }
522
+
523
+ .skeleton-info-value {
472
524
  height: 20px;
473
525
  width: 120px;
474
526
  }
475
527
 
476
- .input-group {
528
+ /* Card Fields */
529
+ .card-field {
477
530
  margin-bottom: 16px;
478
531
  }
479
532
 
480
- .input-group:last-child {
533
+ .card-field:last-child {
481
534
  margin-bottom: 0;
482
535
  }
483
536
 
484
537
  .skeleton-input {
485
- height: 44px;
538
+ height: 36px;
486
539
  width: 100%;
540
+ border-radius: 6px;
487
541
  }
488
542
 
489
- .card-fields-grid {
543
+ .card-row {
490
544
  display: grid;
491
545
  grid-template-columns: 1fr 1fr;
492
546
  gap: 12px;
493
547
  }
494
548
 
549
+ /* Submit Button - matches .recur-submit-button: padding 14px*2 + font 16px * line-height ~1.5 */
495
550
  .skeleton-button {
496
- height: 44px;
551
+ height: 52px;
497
552
  width: 100%;
498
553
  border-radius: 6px;
499
554
  }
500
555
 
556
+ /* Security Note */
501
557
  .security-note {
502
558
  display: flex;
503
559
  align-items: center;
@@ -520,73 +576,67 @@
520
576
  </style>
521
577
 
522
578
  <div class="payment-form-wrapper">
523
- <!-- Header Skeleton -->
579
+ <!-- Header (matches payment-form.ts) -->
524
580
  <div class="form-header">
525
- <div class="skeleton skeleton-title"></div>
526
- <div class="skeleton skeleton-subtitle"></div>
581
+ <h2 class="form-title">\u8A02\u95B1\u4ED8\u6B3E</h2>
582
+ <p class="form-subtitle">\u8ACB\u586B\u5BEB\u4FE1\u7528\u5361\u8CC7\u8A0A\u5B8C\u6210\u8A02\u95B1</p>
527
583
  </div>
528
584
 
529
- <!-- Order Summary - Static labels, skeleton values -->
530
- <div class="skeleton-order-summary">
531
- <h3 class="section-title">\u8A02\u55AE\u6458\u8981</h3>
532
- <div class="skeleton-order-row">
533
- <span class="label">\u65B9\u6848</span>
585
+ <!-- Order Summary (matches createOrderSummarySection) -->
586
+ <div class="order-summary">
587
+ <h3 class="order-summary-title">\u8A02\u55AE\u6458\u8981</h3>
588
+ <div class="order-row">
589
+ <span class="order-label">\u8A02\u95B1\u65B9\u6848</span>
534
590
  <div class="skeleton skeleton-order-value"></div>
535
591
  </div>
536
- <div class="skeleton-order-row">
537
- <span class="label">\u91D1\u984D</span>
592
+ <div class="order-row">
593
+ <span class="order-label">\u8A08\u8CBB\u9031\u671F</span>
538
594
  <div class="skeleton skeleton-order-value"></div>
539
595
  </div>
540
- <div class="skeleton-order-row">
541
- <span class="label">\u9031\u671F</span>
542
- <div class="skeleton skeleton-order-value"></div>
543
- </div>
544
- <div class="skeleton-order-row">
545
- <span class="label">\u7E3D\u8A08</span>
546
- <div class="skeleton skeleton-order-value"></div>
596
+ <div class="order-row">
597
+ <span class="order-label">\u7E3D\u8A08</span>
598
+ <div class="skeleton skeleton-order-total"></div>
547
599
  </div>
548
600
  </div>
549
601
 
550
- <!-- Customer Info Section - Static labels, skeleton inputs -->
602
+ <!-- Customer Info Section (matches createCustomerInfoSection read-only display) -->
551
603
  <div class="form-section">
552
604
  <h3 class="section-title">\u5BA2\u6236\u8CC7\u8A0A</h3>
553
- <div class="input-group">
554
- <div class="label">\u59D3\u540D</div>
555
- <div class="skeleton skeleton-input"></div>
556
- </div>
557
- <div class="input-group">
558
- <div class="label">Email</div>
559
- <div class="skeleton skeleton-input"></div>
560
- </div>
561
- <div class="input-group">
562
- <div class="label">\u96FB\u8A71\uFF08\u9078\u586B\uFF09</div>
563
- <div class="skeleton skeleton-input"></div>
605
+ <div class="customer-info-display">
606
+ <div class="info-row">
607
+ <span class="info-label">\u5BA2\u6236\u59D3\u540D\uFF1A</span>
608
+ <div class="skeleton skeleton-info-value"></div>
609
+ </div>
610
+ <div class="info-row">
611
+ <span class="info-label">\u96FB\u5B50\u90F5\u4EF6\uFF1A</span>
612
+ <div class="skeleton skeleton-info-value" style="width: 160px;"></div>
613
+ </div>
564
614
  </div>
565
615
  </div>
566
616
 
567
- <!-- Card Fields Section - Static labels, skeleton inputs -->
617
+ <!-- Card Fields Section (matches createCardFieldsSection) -->
568
618
  <div class="form-section">
569
619
  <h3 class="section-title">\u4FE1\u7528\u5361\u8CC7\u8A0A</h3>
570
- <div class="input-group">
571
- <div class="label">\u4FE1\u7528\u5361\u865F</div>
620
+ <div class="card-field">
621
+ <label class="label">\u5361\u865F</label>
572
622
  <div class="skeleton skeleton-input"></div>
573
623
  </div>
574
- <div class="card-fields-grid">
575
- <div class="input-group">
576
- <div class="label">\u6709\u6548\u671F\u9650</div>
624
+ <div class="card-row">
625
+ <div class="card-field">
626
+ <label class="label">\u6709\u6548\u671F\u9650</label>
577
627
  <div class="skeleton skeleton-input"></div>
578
628
  </div>
579
- <div class="input-group">
580
- <div class="label">\u5B89\u5168\u78BC</div>
629
+ <div class="card-field">
630
+ <label class="label">\u5B89\u5168\u78BC</label>
581
631
  <div class="skeleton skeleton-input"></div>
582
632
  </div>
583
633
  </div>
584
634
  </div>
585
635
 
586
- <!-- Submit Button Skeleton -->
636
+ <!-- Submit Button -->
587
637
  <div class="skeleton skeleton-button"></div>
588
638
 
589
- <!-- Security Note -->
639
+ <!-- Security Note (matches payment-form.ts) -->
590
640
  <div class="security-note">
591
641
  <svg class="security-icon" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
592
642
  <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" />
@@ -594,7 +644,7 @@
594
644
  <p class="security-text">\u60A8\u7684\u4ED8\u6B3E\u8CC7\u8A0A\u7D93\u904E\u52A0\u5BC6\u4FDD\u8B77</p>
595
645
  </div>
596
646
  </div>
597
- `}};typeof window<"u"&&!customElements.get("recur-payment-form-skeleton")&&customElements.define("recur-payment-form-skeleton",T)});var b={};d(b,{RecurToast:()=>M,RecurToastContainer:()=>f});var M,u,f,g=m(()=>{"use strict";M=class extends HTMLElement{static get observedAttributes(){return["message","type","duration"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.setupAutoDismiss()}get message(){return this.getAttribute("message")||"Notification"}get type(){let e=this.getAttribute("type");return e==="success"||e==="error"?e:"info"}get duration(){let e=this.getAttribute("duration");return e?parseInt(e,10):5e3}setupAutoDismiss(){let e=this.duration;e>0&&setTimeout(()=>this.dismiss(),e)}dismiss(){this.style.animation="recur-toast-slide-out 0.3s ease-in-out",setTimeout(()=>this.remove(),300)}getTypeIcon(){switch(this.type){case"success":return`<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
647
+ `}};typeof window<"u"&&!customElements.get("recur-payment-form-skeleton")&&customElements.define("recur-payment-form-skeleton",P)});var W={};h(W,{RecurToast:()=>M,RecurToastContainer:()=>k});var M,f,k,J=g(()=>{"use strict";M=class extends HTMLElement{static get observedAttributes(){return["message","type","duration"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.setupAutoDismiss()}get message(){return this.getAttribute("message")||"Notification"}get type(){let e=this.getAttribute("type");return e==="success"||e==="error"?e:"info"}get duration(){let e=this.getAttribute("duration");return e?parseInt(e,10):5e3}setupAutoDismiss(){let e=this.duration;e>0&&setTimeout(()=>this.dismiss(),e)}dismiss(){this.style.animation="recur-toast-slide-out 0.3s ease-in-out",setTimeout(()=>this.remove(),300)}getTypeIcon(){switch(this.type){case"success":return`<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
598
648
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
599
649
  </svg>`;case"error":return`<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
600
650
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
@@ -714,7 +764,7 @@
714
764
  </svg>
715
765
  </button>
716
766
  </div>
717
- `,this.shadowRoot.querySelector(".toast-close")?.addEventListener("click",i=>{i.stopPropagation(),this.dismiss()}),this.shadowRoot.querySelector(".toast")?.addEventListener("click",()=>this.dismiss())}static show(e,t="info",r=5e3){let i=f.getInstance(),s=document.createElement("recur-toast");return s.setAttribute("message",e),s.setAttribute("type",t),s.setAttribute("duration",r.toString()),i.appendChild(s),s}},u=class u extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}render(){this.shadowRoot.innerHTML=`
767
+ `,this.shadowRoot.querySelector(".toast-close")?.addEventListener("click",i=>{i.stopPropagation(),this.dismiss()}),this.shadowRoot.querySelector(".toast")?.addEventListener("click",()=>this.dismiss())}static show(e,t="info",r=5e3){let i=k.getInstance(),s=document.createElement("recur-toast");return s.setAttribute("message",e),s.setAttribute("type",t),s.setAttribute("duration",r.toString()),i.appendChild(s),s}},f=class f extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}render(){this.shadowRoot.innerHTML=`
718
768
  <style>
719
769
  :host {
720
770
  position: fixed;
@@ -741,7 +791,7 @@
741
791
  </style>
742
792
 
743
793
  <slot></slot>
744
- `}static getInstance(){return u.instance||(u.instance=document.querySelector("recur-toast-container"),u.instance||(u.instance=document.createElement("recur-toast-container"),document.body.appendChild(u.instance))),u.instance}};n(u,"instance",null);f=u;typeof window<"u"&&!customElements.get("recur-toast")&&customElements.define("recur-toast",M);typeof window<"u"&&!customElements.get("recur-toast-container")&&customElements.define("recur-toast-container",f)});var K={};d(K,{RecurPaymentForm:()=>I});var I,q=m(()=>{"use strict";I=class extends HTMLElement{constructor(){super();n(this,"containerId");n(this,"customStyles");n(this,"_isInitializing",!1);n(this,"_initializationAborted",!1);this.containerId=this.getAttribute("container-id")||`recur-${Date.now()}`,this.customStyles=this.getAttribute("custom-styles")||"",this.attachShadow({mode:"open"})}connectedCallback(){this.render()}disconnectedCallback(){console.log("[PaymentForm] Component disconnected, cleaning up..."),this._initializationAborted=!0,this._paymentSession=null;let t=document.getElementById(`${this.containerId}-submit-btn`);if(t){let r=t.cloneNode(!0);t.parentNode?.replaceChild(r,t)}}static get observedAttributes(){return["custom-styles","customer-name","customer-email","plan-name","amount","billing-period"]}attributeChangedCallback(t,r,i){t==="custom-styles"&&r!==i?(this.customStyles=i||"",this.updateCustomStyles()):r!==i&&this.updateCustomerInfoSection()}render(){this.shadowRoot.innerHTML=`
794
+ `}static getInstance(){return f.instance||(f.instance=document.querySelector("recur-toast-container"),f.instance||(f.instance=document.createElement("recur-toast-container"),document.body.appendChild(f.instance))),f.instance}};a(f,"instance",null);k=f;typeof window<"u"&&!customElements.get("recur-toast")&&customElements.define("recur-toast",M);typeof window<"u"&&!customElements.get("recur-toast-container")&&customElements.define("recur-toast-container",k)});var Z={};h(Z,{RecurPaymentForm:()=>L});var L,G=g(()=>{"use strict";L=class extends HTMLElement{constructor(){super();a(this,"containerId");a(this,"customStyles");a(this,"_isInitializing",!1);a(this,"_initializationAborted",!1);this.containerId=this.getAttribute("container-id")||`recur-${Date.now()}`,this.customStyles=this.getAttribute("custom-styles")||"",this.attachShadow({mode:"open"})}connectedCallback(){this.render()}disconnectedCallback(){console.log("[PaymentForm] Component disconnected, cleaning up..."),this._initializationAborted=!0,this._paymentSession=null;let t=document.getElementById(`${this.containerId}-submit-btn`);if(t){let r=t.cloneNode(!0);t.parentNode?.replaceChild(r,t)}}static get observedAttributes(){return["custom-styles","customer-name","customer-email","plan-name","amount","billing-period"]}attributeChangedCallback(t,r,i){t==="custom-styles"&&r!==i?(this.customStyles=i||"",this.updateCustomStyles()):r!==i&&this.updateCustomerInfoSection()}render(){this.shadowRoot.innerHTML=`
745
795
  <style>
746
796
  /* \u9019\u4E9B\u6A23\u5F0F\u88AB\u9694\u96E2\u5728 Shadow DOM \u5167\uFF0C\u4E0D\u6703\u5F71\u97FF\u5916\u90E8 */
747
797
  :host {
@@ -763,10 +813,10 @@
763
813
  }
764
814
 
765
815
  .form-title {
766
- font-size: 24px;
816
+ font-size: 20px;
767
817
  font-weight: 600;
768
818
  color: #1a202c;
769
- margin: 0 0 8px 0;
819
+ margin: 0 0 4px 0;
770
820
  }
771
821
 
772
822
  .form-subtitle {
@@ -814,8 +864,8 @@
814
864
 
815
865
  <div class="payment-form-wrapper">
816
866
  <div class="form-header">
817
- <h2 class="form-title">\u4ED8\u6B3E\u8CC7\u8A0A</h2>
818
- <p class="form-subtitle">\u8ACB\u586B\u5BEB\u60A8\u7684\u4FE1\u7528\u5361\u8CC7\u8A0A\u4EE5\u5B8C\u6210\u8A02\u95B1</p>
867
+ <h2 class="form-title">\u8A02\u95B1\u4ED8\u6B3E</h2>
868
+ <p class="form-subtitle">\u8ACB\u586B\u5BEB\u4FE1\u7528\u5361\u8CC7\u8A0A\u5B8C\u6210\u8A02\u95B1</p>
819
869
  </div>
820
870
 
821
871
  <!-- Slot for order summary (Light DOM) -->
@@ -851,7 +901,7 @@
851
901
  height: 36px !important;
852
902
  }
853
903
  `;t.textContent=this.customStyles+`
854
- `+r,this.appendChild(t);let i=this.createOrderSummarySection();i.slot="order-summary",this.appendChild(i);let s=this.createCustomerInfoSection();s.slot="customer-info",this.appendChild(s);let a=this.createCardFieldsSection();a.slot="card-fields",this.appendChild(a);let o=this.createActionsSection();o.slot="actions",this.appendChild(o)}updateCustomerInfoSection(){let t=this.querySelector('[slot="customer-info"]');if(t){let r=this.createCustomerInfoSection();r.slot="customer-info",t.replaceWith(r)}}updateCustomStyles(){let t=this.querySelector(`#${this.containerId}-custom-styles`);if(t){let r=`
904
+ `+r,this.appendChild(t);let i=this.createOrderSummarySection();i.slot="order-summary",this.appendChild(i);let s=this.createCustomerInfoSection();s.slot="customer-info",this.appendChild(s);let n=this.createCardFieldsSection();n.slot="card-fields",this.appendChild(n);let o=this.createActionsSection();o.slot="actions",this.appendChild(o)}updateCustomerInfoSection(){let t=this.querySelector('[slot="customer-info"]');if(t){let r=this.createCustomerInfoSection();r.slot="customer-info",t.replaceWith(r)}}updateCustomStyles(){let t=this.querySelector(`#${this.containerId}-custom-styles`);if(t){let r=`
855
905
  /* PAYUNi iframe \u5BB9\u5668\u9AD8\u5EA6\uFF08\u4F7F\u7528\u5BE6\u969B\u7684 container ID\uFF09 */
856
906
  #${this.containerId}-card-no,
857
907
  #${this.containerId}-card-exp,
@@ -896,12 +946,14 @@
896
946
 
897
947
  .order-summary-value {
898
948
  font-size: 14px;
949
+ line-height: 20px;
899
950
  font-weight: 500;
900
951
  color: #2d3748;
901
952
  }
902
953
 
903
954
  .order-summary-total {
904
955
  font-size: 18px;
956
+ line-height: 26px;
905
957
  font-weight: 700;
906
958
  color: #1a202c;
907
959
  }
@@ -950,6 +1002,7 @@
950
1002
 
951
1003
  .recur-info-value {
952
1004
  font-size: 14px;
1005
+ line-height: 20px;
953
1006
  color: #2d3748;
954
1007
  font-weight: 500;
955
1008
  }
@@ -1059,11 +1112,43 @@
1059
1112
  grid-template-columns: 1fr 1fr;
1060
1113
  gap: 12px;
1061
1114
  }
1115
+
1116
+ /* Container needs relative positioning for skeleton overlay */
1117
+ .recur-card-field-container {
1118
+ position: relative;
1119
+ }
1120
+
1121
+ /* Loading skeleton for card fields - shown until PAYUNi iframe loads */
1122
+ .recur-card-skeleton {
1123
+ position: absolute;
1124
+ top: 0;
1125
+ left: 0;
1126
+ height: 36px;
1127
+ width: 100%;
1128
+ background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);
1129
+ background-size: 200% 100%;
1130
+ animation: recur-skeleton-loading 1.5s ease-in-out infinite;
1131
+ border-radius: 4px;
1132
+ z-index: 1;
1133
+ pointer-events: none;
1134
+ }
1135
+
1136
+ /* Hide skeleton when PAYUNi iframe is ready (has content) */
1137
+ .recur-card-skeleton.hidden {
1138
+ display: none;
1139
+ }
1140
+
1141
+ @keyframes recur-skeleton-loading {
1142
+ 0% { background-position: 200% 0; }
1143
+ 100% { background-position: -200% 0; }
1144
+ }
1062
1145
  </style>
1063
1146
 
1064
1147
  <div class="recur-card-field">
1065
1148
  <label class="recur-card-field-label">\u5361\u865F</label>
1066
1149
  <div class="recur-card-field-container" id="${this.containerId}-card-no-wrapper">
1150
+ <!-- Skeleton shown until PAYUNi iframe loads -->
1151
+ <div class="recur-card-skeleton" id="${this.containerId}-card-no-skeleton"></div>
1067
1152
  <!-- PAYUNi \u6703\u5728\u9019\u88E1\u6CE8\u5165 iframe -->
1068
1153
  <div id="${this.containerId}-card-no" class="recur-payuni-iframe"></div>
1069
1154
  </div>
@@ -1073,6 +1158,7 @@
1073
1158
  <div class="recur-card-field">
1074
1159
  <label class="recur-card-field-label">\u6709\u6548\u671F\u9650</label>
1075
1160
  <div class="recur-card-field-container" id="${this.containerId}-card-exp-wrapper">
1161
+ <div class="recur-card-skeleton" id="${this.containerId}-card-exp-skeleton"></div>
1076
1162
  <div id="${this.containerId}-card-exp" class="recur-payuni-iframe"></div>
1077
1163
  </div>
1078
1164
  </div>
@@ -1080,11 +1166,12 @@
1080
1166
  <div class="recur-card-field">
1081
1167
  <label class="recur-card-field-label">\u5B89\u5168\u78BC</label>
1082
1168
  <div class="recur-card-field-container" id="${this.containerId}-card-cvc-wrapper">
1169
+ <div class="recur-card-skeleton" id="${this.containerId}-card-cvc-skeleton"></div>
1083
1170
  <div id="${this.containerId}-card-cvc" class="recur-payuni-iframe"></div>
1084
1171
  </div>
1085
1172
  </div>
1086
1173
  </div>
1087
- `,t}createActionsSection(){let t=document.createElement("div");return t.className="actions-section",t.innerHTML=`
1174
+ `,t}hideCardSkeletons(){[`${this.containerId}-card-no-skeleton`,`${this.containerId}-card-exp-skeleton`,`${this.containerId}-card-cvc-skeleton`].forEach(r=>{let i=document.getElementById(r);i&&i.classList.add("hidden")})}createActionsSection(){let t=document.createElement("div");return t.className="actions-section",t.innerHTML=`
1088
1175
  <style>
1089
1176
  .recur-submit-button {
1090
1177
  width: 100%;
@@ -1138,10 +1225,10 @@
1138
1225
  >
1139
1226
  <span id="${this.containerId}-submit-text">\u78BA\u8A8D\u4ED8\u6B3E</span>
1140
1227
  </button>
1141
- `,t}async initializePayment(t,r){if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before start"),null;if(this._isInitializing=!0,await this.updateComplete(),this._initializationAborted)return console.log("[PaymentForm] Initialization aborted after updateComplete"),this._isInitializing=!1,null;if(!window.UniPayment)throw this._isInitializing=!1,new Error("PAYUNi SDK not loaded");try{let i=document.getElementById(`${this.containerId}-card-no`),s=document.getElementById(`${this.containerId}-card-exp`),a=document.getElementById(`${this.containerId}-card-cvc`);if(!i||!s||!a)return console.log("[PaymentForm] DOM elements not found, likely disconnected"),this._isInitializing=!1,null;if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before createSession"),this._isInitializing=!1,null;let o=window.UniPayment.createSession(t,{env:r==="SANDBOX"?"S":"P",elements:{CardNo:`${this.containerId}-card-no`,CardExp:`${this.containerId}-card-exp`,CardCvc:`${this.containerId}-card-cvc`}});if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before paymentSession.start()"),this._isInitializing=!1,null;try{await o.start()}catch(c){if((c?.message?.includes("1008")||c?.message?.includes("timeout")||c?.code===1008)&&this._initializationAborted)return console.log("[PaymentForm] Caught 1008 timeout error after component disconnect - ignoring"),this._isInitializing=!1,null;throw c}return this._initializationAborted?(console.log("[PaymentForm] Initialization aborted after paymentSession.start()"),this._isInitializing=!1,null):(o.onUpdate?.(c=>{if(this._initializationAborted){console.log("[PaymentForm] Ignoring onUpdate event - component disconnected");return}console.log("[PaymentForm] PAYUNi update:",c);let p=c.status&&c.status.CardNo===!0&&c.status.CardExp===!0&&c.status.CardCvc===!0,v=document.getElementById(`${this.containerId}-submit-btn`);v&&(v.disabled=!p,console.log("[PaymentForm] Submit button disabled:",!p))}),this._initializationAborted?(console.log("[PaymentForm] Initialization aborted before saving session"),this._isInitializing=!1,null):(this._paymentSession=o,this.setupFormSubmission(),this._isInitializing=!1,o))}catch(i){throw this._isInitializing=!1,console.error("[PaymentForm] Failed to initialize payment:",i),i}}setupFormSubmission(){let t=document.getElementById(`${this.containerId}-submit-btn`);t&&t.addEventListener("click",async r=>{if(r.preventDefault(),t.classList.contains("loading"))return;let i,s,a,o=document.getElementById(`${this.containerId}-email`),c=document.getElementById(`${this.containerId}-name`),p=document.getElementById(`${this.containerId}-phone`);if(o&&c){if(i=o.value,s=c.value,a=p?.value,!i||!s){this.showError("\u8ACB\u586B\u5BEB\u59D3\u540D\u548C\u96FB\u5B50\u90F5\u4EF6");return}}else if(i=this.getAttribute("customer-email")||void 0,s=this.getAttribute("customer-name")||void 0,!i||!s){this.showError("\u5BA2\u6236\u8CC7\u8A0A\u4E0D\u5B8C\u6574");return}this.clearError(),this.setButtonLoading(!0),this.dispatchEvent(new CustomEvent("submit",{detail:{customerEmail:i,customerName:s,customerPhone:a,paymentSession:this._paymentSession},bubbles:!0,composed:!0}))})}setButtonLoading(t){let r=document.getElementById(`${this.containerId}-submit-btn`);r&&(t?(r.classList.add("loading"),r.disabled=!0,r.innerHTML=`
1228
+ `,t}async initializePayment(t,r){if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before start"),null;if(this._isInitializing=!0,await this.updateComplete(),this._initializationAborted)return console.log("[PaymentForm] Initialization aborted after updateComplete"),this._isInitializing=!1,null;if(!window.UniPayment)throw this._isInitializing=!1,new Error("PAYUNi SDK not loaded");try{let i=document.getElementById(`${this.containerId}-card-no`),s=document.getElementById(`${this.containerId}-card-exp`),n=document.getElementById(`${this.containerId}-card-cvc`);if(!i||!s||!n)return console.log("[PaymentForm] DOM elements not found, likely disconnected"),this._isInitializing=!1,null;if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before createSession"),this._isInitializing=!1,null;let o=window.UniPayment.createSession(t,{env:r==="SANDBOX"?"S":"P",elements:{CardNo:`${this.containerId}-card-no`,CardExp:`${this.containerId}-card-exp`,CardCvc:`${this.containerId}-card-cvc`}});if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before paymentSession.start()"),this._isInitializing=!1,null;try{await o.start()}catch(l){if((l?.message?.includes("1008")||l?.message?.includes("timeout")||l?.code===1008)&&this._initializationAborted)return console.log("[PaymentForm] Caught 1008 timeout error after component disconnect - ignoring"),this._isInitializing=!1,null;throw l}return this._initializationAborted?(console.log("[PaymentForm] Initialization aborted after paymentSession.start()"),this._isInitializing=!1,null):(this.hideCardSkeletons(),o.onUpdate?.(l=>{if(this._initializationAborted){console.log("[PaymentForm] Ignoring onUpdate event - component disconnected");return}console.log("[PaymentForm] PAYUNi update:",l);let d=l.status&&l.status.CardNo===!0&&l.status.CardExp===!0&&l.status.CardCvc===!0,y=document.getElementById(`${this.containerId}-submit-btn`);y&&(y.disabled=!d,console.log("[PaymentForm] Submit button disabled:",!d))}),this._initializationAborted?(console.log("[PaymentForm] Initialization aborted before saving session"),this._isInitializing=!1,null):(this._paymentSession=o,this.setupFormSubmission(),this._isInitializing=!1,o))}catch(i){throw this._isInitializing=!1,console.error("[PaymentForm] Failed to initialize payment:",i),i}}setupFormSubmission(){let t=document.getElementById(`${this.containerId}-submit-btn`);t&&t.addEventListener("click",async r=>{if(r.preventDefault(),t.classList.contains("loading"))return;let i,s,n,o=document.getElementById(`${this.containerId}-email`),l=document.getElementById(`${this.containerId}-name`),d=document.getElementById(`${this.containerId}-phone`);if(o&&l){if(i=o.value,s=l.value,n=d?.value,!i||!s){this.showError("\u8ACB\u586B\u5BEB\u59D3\u540D\u548C\u96FB\u5B50\u90F5\u4EF6");return}}else if(i=this.getAttribute("customer-email")||void 0,s=this.getAttribute("customer-name")||void 0,!i||!s){this.showError("\u5BA2\u6236\u8CC7\u8A0A\u4E0D\u5B8C\u6574");return}this.clearError(),this.setButtonLoading(!0),this.dispatchEvent(new CustomEvent("submit",{detail:{customerEmail:i,customerName:s,customerPhone:n,paymentSession:this._paymentSession},bubbles:!0,composed:!0}))})}setButtonLoading(t){let r=document.getElementById(`${this.containerId}-submit-btn`);r&&(t?(r.classList.add("loading"),r.disabled=!0,r.innerHTML=`
1142
1229
  <span class="recur-loading-spinner"></span>
1143
1230
  <span>\u8655\u7406\u4E2D...</span>
1144
- `):(r.classList.remove("loading"),r.disabled=!1,r.innerHTML='<span id="'+this.containerId+'-submit-text">\u78BA\u8A8D\u4ED8\u6B3E</span>'))}resetButton(){this.setButtonLoading(!1)}showError(t){let r=this.querySelector(".recur-sdk__error-container");r||(r=document.createElement("div"),r.className="recur-sdk__error-container",r.style.cssText="margin-bottom: 16px;",this.insertBefore(r,this.firstChild));let i=document.createElement("recur-error-display");i.setAttribute("error",t),i.setAttribute("dismissible","true"),r.innerHTML="",r.appendChild(i),i.scrollIntoView({behavior:"smooth",block:"center"})}clearError(){let t=this.querySelector(".recur-sdk__error-container");t&&(t.innerHTML="")}updateComplete(){return new Promise(t=>{if(this.isConnected)setTimeout(t,0);else{let r=new MutationObserver(()=>{this.isConnected&&(r.disconnect(),setTimeout(t,0))});r.observe(document.body,{childList:!0,subtree:!0})}})}getFormData(){return{email:document.getElementById(`${this.containerId}-email`)?.value,name:document.getElementById(`${this.containerId}-name`)?.value,phone:document.getElementById(`${this.containerId}-phone`)?.value}}setFormData(t){if(t.email){let r=document.getElementById(`${this.containerId}-email`);r&&(r.value=t.email)}if(t.name){let r=document.getElementById(`${this.containerId}-name`);r&&(r.value=t.name)}if(t.phone){let r=document.getElementById(`${this.containerId}-phone`);r&&(r.value=t.phone)}}};customElements.get("recur-payment-form")||customElements.define("recur-payment-form",I)});var Y={};d(Y,{RecurCheckoutButton:()=>S});var S,V=m(()=>{"use strict";S=class extends HTMLElement{constructor(){super();n(this,"_isLoading",!1);n(this,"handleClick",async t=>{if(t.preventDefault(),this._isLoading||this.hasAttribute("disabled"))return;let r=this.getAttribute("publishable-key"),i=this.getAttribute("product-id"),s=this.getAttribute("success-url"),a=this.getAttribute("cancel-url");if(!r){this.dispatchError("Missing required attribute: publishable-key");return}if(!i){this.dispatchError("Missing required attribute: product-id");return}if(!s){this.dispatchError("Missing required attribute: success-url");return}if(!a){this.dispatchError("Missing required attribute: cancel-url");return}this._isLoading=!0,this.render(),this.setupEventListeners();try{let o=await this.createCheckoutSession({publishableKey:r,productId:i,successUrl:this.resolveUrl(s),cancelUrl:this.resolveUrl(a),customerEmail:this.getAttribute("customer-email")||void 0,mode:this.getAttribute("mode")});this.dispatchEvent(new CustomEvent("checkout-started",{detail:{sessionId:o.id,url:o.url},bubbles:!0,composed:!0})),window.location.href=o.url}catch(o){this._isLoading=!1,this.render(),this.setupEventListeners(),this.dispatchError(o.message||"Failed to create checkout session")}});this.attachShadow({mode:"open"})}static get observedAttributes(){return["publishable-key","product-id","success-url","cancel-url","customer-email","mode","button-text","button-style","disabled"]}connectedCallback(){this.render(),this.setupEventListeners()}disconnectedCallback(){let t=this.shadowRoot?.querySelector("button");t&&t.removeEventListener("click",this.handleClick)}attributeChangedCallback(t,r,i){r!==i&&this.render()}render(){let t=this.getAttribute("button-text")||this.textContent?.trim()||"\u8A02\u95B1",r=this.getAttribute("button-style")||"primary",i=this.hasAttribute("disabled")||this._isLoading;this.shadowRoot.innerHTML=`
1231
+ `):(r.classList.remove("loading"),r.disabled=!1,r.innerHTML='<span id="'+this.containerId+'-submit-text">\u78BA\u8A8D\u4ED8\u6B3E</span>'))}resetButton(){this.setButtonLoading(!1)}showError(t){let r=this.querySelector(".recur-sdk__error-container");r||(r=document.createElement("div"),r.className="recur-sdk__error-container",r.style.cssText="margin-bottom: 16px;",this.insertBefore(r,this.firstChild));let i=document.createElement("recur-error-display");i.setAttribute("error",t),i.setAttribute("dismissible","true"),r.innerHTML="",r.appendChild(i),i.scrollIntoView({behavior:"smooth",block:"center"})}clearError(){let t=this.querySelector(".recur-sdk__error-container");t&&(t.innerHTML="")}updateComplete(){return new Promise(t=>{if(this.isConnected)setTimeout(t,0);else{let r=new MutationObserver(()=>{this.isConnected&&(r.disconnect(),setTimeout(t,0))});r.observe(document.body,{childList:!0,subtree:!0})}})}getFormData(){return{email:document.getElementById(`${this.containerId}-email`)?.value,name:document.getElementById(`${this.containerId}-name`)?.value,phone:document.getElementById(`${this.containerId}-phone`)?.value}}setFormData(t){if(t.email){let r=document.getElementById(`${this.containerId}-email`);r&&(r.value=t.email)}if(t.name){let r=document.getElementById(`${this.containerId}-name`);r&&(r.value=t.name)}if(t.phone){let r=document.getElementById(`${this.containerId}-phone`);r&&(r.value=t.phone)}}};customElements.get("recur-payment-form")||customElements.define("recur-payment-form",L)});var Q={};h(Q,{RecurCheckoutButton:()=>U});var U,ee=g(()=>{"use strict";U=class extends HTMLElement{constructor(){super();a(this,"_isLoading",!1);a(this,"handleClick",async t=>{if(t.preventDefault(),this._isLoading||this.hasAttribute("disabled"))return;let r=this.getAttribute("publishable-key"),i=this.getAttribute("product-id"),s=this.getAttribute("success-url"),n=this.getAttribute("cancel-url");if(!r){this.dispatchError("Missing required attribute: publishable-key");return}if(!i){this.dispatchError("Missing required attribute: product-id");return}if(!s){this.dispatchError("Missing required attribute: success-url");return}if(!n){this.dispatchError("Missing required attribute: cancel-url");return}this._isLoading=!0,this.render(),this.setupEventListeners();try{let o=await this.createCheckoutSession({publishableKey:r,productId:i,successUrl:this.resolveUrl(s),cancelUrl:this.resolveUrl(n),customerEmail:this.getAttribute("customer-email")||void 0,mode:this.getAttribute("mode")});this.dispatchEvent(new CustomEvent("checkout-started",{detail:{sessionId:o.id,url:o.url},bubbles:!0,composed:!0})),window.location.href=o.url}catch(o){this._isLoading=!1,this.render(),this.setupEventListeners(),this.dispatchError(o.message||"Failed to create checkout session")}});this.attachShadow({mode:"open"})}static get observedAttributes(){return["publishable-key","product-id","success-url","cancel-url","customer-email","mode","button-text","button-style","disabled"]}connectedCallback(){this.render(),this.setupEventListeners()}disconnectedCallback(){let t=this.shadowRoot?.querySelector("button");t&&t.removeEventListener("click",this.handleClick)}attributeChangedCallback(t,r,i){r!==i&&this.render()}render(){let t=this.getAttribute("button-text")||this.textContent?.trim()||"\u8A02\u95B1",r=this.getAttribute("button-style")||"primary",i=this.hasAttribute("disabled")||this._isLoading;this.shadowRoot.innerHTML=`
1145
1232
  <style>
1146
1233
  :host {
1147
1234
  display: inline-block;
@@ -1240,57 +1327,7 @@
1240
1327
  ${this._isLoading?'<span class="spinner"></span>':""}
1241
1328
  <span>${this._isLoading?"\u8655\u7406\u4E2D...":t}</span>
1242
1329
  </button>
1243
- `}setupEventListeners(){let t=this.shadowRoot?.querySelector("button");t&&t.addEventListener("click",this.handleClick)}async createCheckoutSession(t){let r=this.getApiBaseUrl(),i={productId:t.productId,successUrl:t.successUrl,cancelUrl:t.cancelUrl};t.mode&&(i.mode=t.mode),t.customerEmail&&(i.customerEmail=t.customerEmail);let s=await fetch(`${r}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(i)});if(!s.ok){let a=await s.json().catch(()=>({}));throw new Error(a.error?.message||`HTTP ${s.status}: Failed to create checkout session`)}return s.json()}getApiBaseUrl(){let t=this.getAttribute("api-base-url");if(t)return t;if(typeof window<"u"){let r=window.location.hostname;if(r==="localhost"||r.includes(".test")||r.includes(".local")||r==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}resolveUrl(t){return t.startsWith("/")?`${window.location.origin}${t}`:t}dispatchError(t){console.error("[recur-checkout]",t),this.dispatchEvent(new CustomEvent("checkout-error",{detail:{message:t},bubbles:!0,composed:!0}))}};typeof window<"u"&&!customElements.get("recur-checkout")&&customElements.define("recur-checkout",S)});var ie={};d(ie,{RecurCheckout:()=>y,RecurElements:()=>h,createElements:()=>_,default:()=>re,init:()=>X});async function te(){if(typeof window>"u"){console.warn("[Recur SDK] Cannot register Web Components: window is not defined");return}await Promise.all([Promise.resolve().then(()=>(H(),U)),Promise.resolve().then(()=>(A(),$)),Promise.resolve().then(()=>(D(),B)),Promise.resolve().then(()=>(O(),N)),Promise.resolve().then(()=>(j(),F)),Promise.resolve().then(()=>(g(),b)),Promise.resolve().then(()=>(q(),K)),Promise.resolve().then(()=>(V(),Y))]);let e=["recur-loading-spinner","recur-success-message","recur-error-display","recur-skeleton-loader","recur-payment-form-skeleton","recur-toast","recur-toast-container","recur-payment-form","recur-checkout"].filter(t=>!customElements.get(t));e.length>0&&console.warn("[Recur SDK] The following components are not registered:",e)}typeof window<"u"&&te();var L=class{constructor(e){n(this,"config");if(!e.publishableKey)throw new Error("publishableKey is required");this.config={baseUrl:"https://api.recur.tw",...e}}async createSubscription(e){let{planId:t,customerName:r,customerEmail:i,customerPhone:s}=e;if(!t)throw new Error("planId is required");let a=await fetch(`${this.config.baseUrl}/v1/subscriptions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({planId:t,customerName:r,customerEmail:i,customerPhone:s})});if(!a.ok){let o=await a.json().catch(()=>({}));throw{code:o.error||"CHECKOUT_FAILED",message:o.message||"Failed to initiate checkout",details:o}}return await a.json()}async fetchPlans(){let e=await fetch(`${this.config.baseUrl}/v1/plans`,{method:"GET",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey}});if(!e.ok){let t=await e.json().catch(()=>({}));throw{code:t.error||"FETCH_PLANS_FAILED",message:t.message||"Failed to fetch plans",details:t}}return await e.json()}getConfig(){return{...this.config}}};var R=class{constructor(e){n(this,"overlay",null);n(this,"modal",null);n(this,"iframe",null);n(this,"onClose");n(this,"handleMessage",e=>{e.origin===window.location.origin&&(e.data?.type==="RECUR_PAYMENT_COMPLETE"?this.close():e.data?.type==="RECUR_PAYMENT_CANCEL"&&this.close())});this.onClose=e}open(e){this.overlay=document.createElement("div"),this.overlay.style.cssText=`
1244
- position: fixed;
1245
- top: 0;
1246
- left: 0;
1247
- right: 0;
1248
- bottom: 0;
1249
- background: rgba(0, 0, 0, 0.5);
1250
- z-index: 9998;
1251
- display: flex;
1252
- align-items: center;
1253
- justify-content: center;
1254
- padding: 20px;
1255
- `,this.modal=document.createElement("div"),this.modal.style.cssText=`
1256
- position: relative;
1257
- background: white;
1258
- border-radius: 8px;
1259
- width: 100%;
1260
- max-width: 600px;
1261
- height: 90vh;
1262
- max-height: 700px;
1263
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
1264
- display: flex;
1265
- flex-direction: column;
1266
- overflow: hidden;
1267
- z-index: 9999;
1268
- `;let t=document.createElement("button");t.innerHTML="\u2715",t.style.cssText=`
1269
- position: absolute;
1270
- top: 12px;
1271
- right: 12px;
1272
- width: 32px;
1273
- height: 32px;
1274
- border: none;
1275
- background: rgba(0, 0, 0, 0.1);
1276
- border-radius: 50%;
1277
- cursor: pointer;
1278
- font-size: 18px;
1279
- line-height: 1;
1280
- z-index: 10000;
1281
- transition: background 0.2s;
1282
- color: #333;
1283
- `,t.onmouseover=()=>{t.style.background="rgba(0, 0, 0, 0.2)"},t.onmouseout=()=>{t.style.background="rgba(0, 0, 0, 0.1)"},t.onclick=()=>this.close(),this.iframe=document.createElement("iframe"),this.iframe.src=e,this.iframe.style.cssText=`
1284
- width: 100%;
1285
- height: 100%;
1286
- border: none;
1287
- border-radius: 8px;
1288
- `,this.iframe.setAttribute("allow","payment"),this.iframe.setAttribute("sandbox","allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"),this.modal.appendChild(t),this.modal.appendChild(this.iframe),this.overlay.appendChild(this.modal),document.body.appendChild(this.overlay),document.body.style.overflow="hidden",this.overlay.onclick=r=>{r.target===this.overlay&&this.close()},window.addEventListener("message",this.handleMessage)}close(){this.overlay&&this.overlay.parentNode&&this.overlay.parentNode.removeChild(this.overlay),document.body.style.overflow="",this.overlay=null,this.modal=null,this.iframe=null,window.removeEventListener("message",this.handleMessage),this.onClose&&this.onClose()}};var P=class{constructor(e,t){n(this,"container");n(this,"iframe",null);n(this,"onClose");n(this,"handleMessage",e=>{e.origin===window.location.origin&&(e.data?.type==="RECUR_PAYMENT_COMPLETE"?this.remove():e.data?.type==="RECUR_PAYMENT_CANCEL"&&this.remove())});if(typeof e=="string"){let r=document.querySelector(e);if(!r)throw new Error(`Container element not found: ${e}`);this.container=r}else this.container=e;this.onClose=t}embed(e){this.container.innerHTML="",this.iframe=document.createElement("iframe"),this.iframe.src=e,this.iframe.style.cssText=`
1289
- width: 100%;
1290
- height: 600px;
1291
- border: 1px solid #e5e7eb;
1292
- border-radius: 8px;
1293
- `,this.iframe.setAttribute("allow","payment"),this.iframe.setAttribute("sandbox","allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"),this.container.appendChild(this.iframe),window.addEventListener("message",this.handleMessage)}remove(){this.iframe&&this.iframe.parentNode&&this.iframe.parentNode.removeChild(this.iframe),this.iframe=null,window.removeEventListener("message",this.handleMessage),this.onClose&&this.onClose()}};var z=class{constructor(e,t){n(this,"config");n(this,"options");n(this,"container");n(this,"checkoutId",null);n(this,"sdkToken",null);n(this,"sdkEnv","S");n(this,"payuniSDK",null);n(this,"isFormValid",!1);if(this.config=e,this.options=t,typeof t.container=="string"){let r=document.querySelector(t.container);if(!r)throw new Error(`Container not found: ${t.container}`);this.container=r}else this.container=t.container}async render(){try{await this.initCheckout(),this.renderHTML(),await this.loadPayUniSDK(),await this.initPayUniSDK(),this.setupFormSubmit()}catch(e){this.handleError(e)}}getBaseUrl(){if(this.config.baseUrl)return this.config.baseUrl;if(typeof window<"u"){let e=window.location.hostname;if(e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}async initCheckout(){let e=this.getBaseUrl(),t=await fetch(`${e}/v1/checkouts`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({productId:this.options.planId,customerEmail:this.options.customerEmail,customerName:this.options.customerName,customerPhone:this.options.customerPhone})});if(!t.ok){let i=await t.json().catch(()=>({}));throw new Error(i.error||"Failed to initialize checkout")}let r=await t.json();this.checkoutId=r.checkout.id,this.sdkToken=r.sdkToken,this.sdkEnv=this.config.publishableKey.startsWith("pk_test_")?"S":"P"}renderHTML(){this.container.innerHTML=`
1330
+ `}setupEventListeners(){let t=this.shadowRoot?.querySelector("button");t&&t.addEventListener("click",this.handleClick)}async createCheckoutSession(t){let r=this.getApiBaseUrl(),i={productId:t.productId,successUrl:t.successUrl,cancelUrl:t.cancelUrl};t.mode&&(i.mode=t.mode),t.customerEmail&&(i.customerEmail=t.customerEmail);let s=await fetch(`${r}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(i)});if(!s.ok){let n=await s.json().catch(()=>({}));throw new Error(n.error?.message||`HTTP ${s.status}: Failed to create checkout session`)}return s.json()}getApiBaseUrl(){let t=this.getAttribute("api-base-url");if(t)return t;if(typeof window<"u"){let r=window.location.hostname;if(r==="localhost"||r.includes(".test")||r.includes(".local")||r==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}resolveUrl(t){return t.startsWith("/")?`${window.location.origin}${t}`:t}dispatchError(t){console.error("[recur-checkout]",t),this.dispatchEvent(new CustomEvent("checkout-error",{detail:{message:t},bubbles:!0,composed:!0}))}};typeof window<"u"&&!customElements.get("recur-checkout")&&customElements.define("recur-checkout",U)});var ye={};h(ye,{RecurCheckout:()=>w,RecurElements:()=>v,createElements:()=>$,default:()=>ge,init:()=>ie});async function he(){if(typeof window>"u"){console.warn("[Recur SDK] Cannot register Web Components: window is not defined");return}await Promise.all([Promise.resolve().then(()=>(N(),B)),Promise.resolve().then(()=>(O(),K)),Promise.resolve().then(()=>(j(),F)),Promise.resolve().then(()=>(q(),Y)),Promise.resolve().then(()=>(X(),V)),Promise.resolve().then(()=>(J(),W)),Promise.resolve().then(()=>(G(),Z)),Promise.resolve().then(()=>(ee(),Q))]);let e=["recur-loading-spinner","recur-success-message","recur-error-display","recur-skeleton-loader","recur-payment-form-skeleton","recur-toast","recur-toast-container","recur-payment-form","recur-checkout"].filter(t=>!customElements.get(t));e.length>0&&console.warn("[Recur SDK] The following components are not registered:",e)}typeof window<"u"&&he();var z=class{constructor(e){a(this,"config");if(!e.publishableKey)throw new Error("publishableKey is required");this.config={baseUrl:"https://api.recur.tw",...e}}async createSubscription(e){let{planId:t,customerName:r,customerEmail:i,customerPhone:s}=e;if(!t)throw new Error("planId is required");let n=await fetch(`${this.config.baseUrl}/v1/subscriptions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({planId:t,customerName:r,customerEmail:i,customerPhone:s})});if(!n.ok){let o=await n.json().catch(()=>({}));throw{code:o.error||"CHECKOUT_FAILED",message:o.message||"Failed to initiate checkout",details:o}}return await n.json()}async fetchPlans(){let e=await fetch(`${this.config.baseUrl}/v1/plans`,{method:"GET",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey}});if(!e.ok){let t=await e.json().catch(()=>({}));throw{code:t.error||"FETCH_PLANS_FAILED",message:t.message||"Failed to fetch plans",details:t}}return await e.json()}getConfig(){return{...this.config}}};var _=class{constructor(e,t){a(this,"config");a(this,"options");a(this,"container");a(this,"checkoutId",null);a(this,"sdkToken",null);a(this,"sdkEnv","S");a(this,"payuniSDK",null);a(this,"isFormValid",!1);if(this.config=e,this.options=t,typeof t.container=="string"){let r=document.querySelector(t.container);if(!r)throw new Error(`Container not found: ${t.container}`);this.container=r}else this.container=t.container}async render(){try{await this.initCheckout(),this.renderHTML(),await this.loadPayUniSDK(),await this.initPayUniSDK(),this.setupFormSubmit()}catch(e){this.handleError(e)}}getBaseUrl(){if(this.config.baseUrl)return this.config.baseUrl;if(typeof window<"u"){let e=window.location.hostname;if(e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}async initCheckout(){let e=this.getBaseUrl(),t=await fetch(`${e}/v1/checkouts`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({productId:this.options.planId,customerEmail:this.options.customerEmail,customerName:this.options.customerName,customerPhone:this.options.customerPhone})});if(!t.ok){let i=await t.json().catch(()=>({}));throw new Error(i.error||"Failed to initialize checkout")}let r=await t.json();this.checkoutId=r.checkout.id,this.sdkToken=r.sdkToken,this.sdkEnv=this.config.publishableKey.startsWith("pk_test_")?"S":"P"}renderHTML(){this.container.innerHTML=`
1294
1331
  <div class="recur-embedded-checkout" style="max-width: 400px; margin: 0 auto; padding: 20px; font-family: system-ui, -apple-system, sans-serif;">
1295
1332
  <div class="recur-checkout-header" style="margin-bottom: 24px;">
1296
1333
  <h2 style="margin: 0 0 8px 0; font-size: 20px; font-weight: 600; color: #111;">Subscribe</h2>
@@ -1372,227 +1409,60 @@
1372
1409
  </p>
1373
1410
  </form>
1374
1411
  </div>
1375
- `}async loadPayUniSDK(){return new Promise((e,t)=>{if(window.UniPayment){e();return}let r=document.createElement("script");r.src=this.sdkEnv==="P"?"https://vendor.payuni.com.tw/sdk/uni-payment.js":"https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",r.async=!0,r.onload=()=>e(),r.onerror=()=>t(new Error("Failed to load PAYUNi SDK")),document.head.appendChild(r)})}async initPayUniSDK(){if(!this.sdkToken)throw new Error("SDK token not initialized");let e=window.UniPayment;if(!e)throw new Error("PAYUNi SDK not loaded");let t={env:this.sdkEnv,useInst:!1,elements:{CardNo:"recur-card-number",CardExp:"recur-card-exp",CardCvc:"recur-card-cvc"},style:{color:"#111827",errorColor:"#dc2626",fontSize:"14px",fontWeight:"400",lineHeight:"24px"}};this.payuniSDK=e.createSession(this.sdkToken,t),await this.payuniSDK.start(),this.payuniSDK.onUpdate(r=>{let i=r?.status;i&&(this.isFormValid=i.CardNo===!0&&i.CardExp===!0&&i.CardCvc===!0,this.updateSubmitButton())})}updateSubmitButton(){let e=document.getElementById("recur-submit-btn");e&&(e.disabled=!this.isFormValid,e.style.opacity=this.isFormValid?"1":"0.5",e.style.cursor=this.isFormValid?"pointer":"not-allowed")}setupFormSubmit(){let e=document.getElementById("recur-checkout-form");e&&e.addEventListener("submit",async t=>{t.preventDefault(),await this.handleSubmit()})}async handleSubmit(){try{this.showLoading(!0),this.hideError();let e=document.getElementById("recur-email").value,t=document.getElementById("recur-name").value,r=document.getElementById("recur-phone").value;if(!e||!t)throw new Error("Please fill in all required fields");if(!this.checkoutId)throw new Error("Checkout session not initialized");if(!this.payuniSDK)throw new Error("Payment system not initialized");let i=await this.payuniSDK.getTradeResult();if(i.Status!=="SUCCESS")throw new Error(i.Message||"Card validation failed");let s=i.EncryptInfo||i.creditToken;if(!s)throw console.error("[Recur SDK] Missing payment token. Available fields:",Object.keys(i)),new Error("Missing payment token");let a=this.getBaseUrl(),o=await fetch(`${a}/v1/checkouts/${this.checkoutId}/pay`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({creditToken:s,timestamp:i.HashTimestamp||i.timestamp})});if(!o.ok){let v=await o.json().catch(()=>({}));throw new Error(v.error||"Failed to process payment")}let c=await o.json(),p={subscription:{id:c.subscription?.id||c.charge?.id||"",status:c.success?"active":"failed",planId:this.options.planId,planName:"",amount:c.charge?.amount||0,billingPeriod:c.subscription?.billingPeriod||"MONTHLY",trialDays:null},subscriber:{id:"",email:document.getElementById("recur-email")?.value||"",name:document.getElementById("recur-name")?.value||""},nextSteps:{getSdkToken:"",completeSubscription:""}};this.options.onSuccess&&this.options.onSuccess(p),this.showSuccess()}catch(e){this.handleError(e)}finally{this.showLoading(!1)}}showLoading(e){let t=document.getElementById("recur-submit-btn");t&&(t.disabled=e,t.textContent=e?"Processing...":"Subscribe Now")}showError(e){let t=document.getElementById("recur-error");t&&(t.textContent=e,t.style.display="block")}hideError(){let e=document.getElementById("recur-error");e&&(e.style.display="none")}showSuccess(){this.container.innerHTML="";let e=document.createElement("recur-success-message");e.setAttribute("title","Subscription Complete!"),e.setAttribute("message","Thank you for subscribing. You will receive a confirmation email shortly."),this.container.appendChild(e)}handleError(e){let t=e?.message||"An error occurred";this.showError(t);let r={code:"CHECKOUT_ERROR",message:t};this.options.onError&&this.options.onError(r)}};var h=class{constructor(e){n(this,"publishableKey");n(this,"baseUrl");n(this,"embedUrl");n(this,"iframe",null);n(this,"container",null);n(this,"sessionId",null);n(this,"timestamp",null);n(this,"creditToken",null);n(this,"cardToken",null);n(this,"cardTimestamp",null);n(this,"eventHandlers",new Map);typeof e=="string"?(this.publishableKey=e,this.baseUrl=this.getDefaultBaseUrl(),this.embedUrl=this.getDefaultEmbedUrl()):(this.publishableKey=e.publishableKey,this.baseUrl=e.baseUrl||this.getDefaultBaseUrl(),this.embedUrl=e.embedUrl||this.getDefaultEmbedUrl()),window.addEventListener("message",this.handleMessage.bind(this))}async mount(e){let t=typeof e=="string"?document.querySelector(e):e;if(!t)throw new Error(`Container not found: ${e}`);return this.container=t,this.iframe=document.createElement("iframe"),this.iframe.src=`${this.embedUrl}/elements?key=${encodeURIComponent(this.publishableKey)}`,this.iframe.style.cssText=`
1412
+ `}async loadPayUniSDK(){return new Promise((e,t)=>{if(window.UniPayment){e();return}let r=document.createElement("script");r.src=this.sdkEnv==="P"?"https://vendor.payuni.com.tw/sdk/uni-payment.js":"https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",r.async=!0,r.onload=()=>e(),r.onerror=()=>t(new Error("Failed to load PAYUNi SDK")),document.head.appendChild(r)})}async initPayUniSDK(){if(!this.sdkToken)throw new Error("SDK token not initialized");let e=window.UniPayment;if(!e)throw new Error("PAYUNi SDK not loaded");let t={env:this.sdkEnv,useInst:!1,elements:{CardNo:"recur-card-number",CardExp:"recur-card-exp",CardCvc:"recur-card-cvc"},style:{color:"#111827",errorColor:"#dc2626",fontSize:"14px",fontWeight:"400",lineHeight:"24px"}};this.payuniSDK=e.createSession(this.sdkToken,t),await this.payuniSDK.start(),this.payuniSDK.onUpdate(r=>{let i=r?.status;i&&(this.isFormValid=i.CardNo===!0&&i.CardExp===!0&&i.CardCvc===!0,this.updateSubmitButton())})}updateSubmitButton(){let e=document.getElementById("recur-submit-btn");e&&(e.disabled=!this.isFormValid,e.style.opacity=this.isFormValid?"1":"0.5",e.style.cursor=this.isFormValid?"pointer":"not-allowed")}setupFormSubmit(){let e=document.getElementById("recur-checkout-form");e&&e.addEventListener("submit",async t=>{t.preventDefault(),await this.handleSubmit()})}async handleSubmit(){try{this.showLoading(!0),this.hideError();let e=document.getElementById("recur-email").value,t=document.getElementById("recur-name").value,r=document.getElementById("recur-phone").value;if(!e||!t)throw new Error("Please fill in all required fields");if(!this.checkoutId)throw new Error("Checkout session not initialized");if(!this.payuniSDK)throw new Error("Payment system not initialized");let i=await this.payuniSDK.getTradeResult();if(i.Status!=="SUCCESS")throw new Error(i.Message||"Card validation failed");let s=i.EncryptInfo||i.creditToken;if(!s)throw console.error("[Recur SDK] Missing payment token. Available fields:",Object.keys(i)),new Error("Missing payment token");let n=this.getBaseUrl(),o=await fetch(`${n}/v1/checkouts/${this.checkoutId}/pay`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({creditToken:s,timestamp:i.HashTimestamp||i.timestamp})});if(!o.ok){let y=await o.json().catch(()=>({}));throw new Error(y.error||"Failed to process payment")}let l=await o.json(),d={subscription:{id:l.subscription?.id||l.charge?.id||"",status:l.success?"active":"failed",planId:this.options.planId,planName:"",amount:l.charge?.amount||0,billingPeriod:l.subscription?.billingPeriod||"MONTHLY",trialDays:null},subscriber:{id:"",email:document.getElementById("recur-email")?.value||"",name:document.getElementById("recur-name")?.value||""},nextSteps:{getSdkToken:"",completeSubscription:""}};this.options.onSuccess&&this.options.onSuccess(d),this.showSuccess()}catch(e){this.handleError(e)}finally{this.showLoading(!1)}}showLoading(e){let t=document.getElementById("recur-submit-btn");t&&(t.disabled=e,t.textContent=e?"Processing...":"Subscribe Now")}showError(e){let t=document.getElementById("recur-error");t&&(t.textContent=e,t.style.display="block")}hideError(){let e=document.getElementById("recur-error");e&&(e.style.display="none")}showSuccess(){this.container.innerHTML="";let e=document.createElement("recur-success-message");e.setAttribute("title","Subscription Complete!"),e.setAttribute("message","Thank you for subscribing. You will receive a confirmation email shortly."),this.container.appendChild(e)}handleError(e){let t=e?.message||"An error occurred";this.showError(t);let r={code:"CHECKOUT_ERROR",message:t};this.options.onError&&this.options.onError(r)}};var v=class{constructor(e){a(this,"publishableKey");a(this,"baseUrl");a(this,"embedUrl");a(this,"iframe",null);a(this,"container",null);a(this,"sessionId",null);a(this,"timestamp",null);a(this,"creditToken",null);a(this,"cardToken",null);a(this,"cardTimestamp",null);a(this,"eventHandlers",new Map);typeof e=="string"?(this.publishableKey=e,this.baseUrl=this.getDefaultBaseUrl(),this.embedUrl=this.getDefaultEmbedUrl()):(this.publishableKey=e.publishableKey,this.baseUrl=e.baseUrl||this.getDefaultBaseUrl(),this.embedUrl=e.embedUrl||this.getDefaultEmbedUrl()),window.addEventListener("message",this.handleMessage.bind(this))}async mount(e){let t=typeof e=="string"?document.querySelector(e):e;if(!t)throw new Error(`Container not found: ${e}`);return this.container=t,this.iframe=document.createElement("iframe"),this.iframe.src=`${this.embedUrl}/elements?key=${encodeURIComponent(this.publishableKey)}`,this.iframe.style.cssText=`
1376
1413
  width: 100%;
1377
1414
  border: none;
1378
1415
  min-height: 200px;
1379
1416
  display: block;
1380
1417
  user-select: none;
1381
1418
  transition: height 0.35s ease, opacity 0.4s ease 0.1s;
1382
- `.replace(/\s+/g," ").trim(),this.iframe.allow="payment *",this.iframe.setAttribute("title","Secure payment input frame"),this.iframe.setAttribute("role","presentation"),this.iframe.setAttribute("scrolling","no"),this.iframe.setAttribute("frameBorder","0"),this.container.innerHTML="",this.container.appendChild(this.iframe),new Promise((r,i)=>{let s=setTimeout(()=>{i(new Error("Elements initialization timeout"))},3e4),a=()=>{clearTimeout(s),this.off("ready",a),r()},o=c=>{clearTimeout(s),this.off("error",o),i(new Error(c.message||"Elements initialization failed"))};this.on("ready",a),this.on("error",o)})}on(e,t){this.eventHandlers.has(e)||this.eventHandlers.set(e,new Set),this.eventHandlers.get(e).add(t)}off(e,t){let r=this.eventHandlers.get(e);r&&r.delete(t)}emit(e,t){let r=this.eventHandlers.get(e);r&&r.forEach(i=>i(t))}handleMessage(e){if(!this.isValidOrigin(e.origin))return;let{type:t,data:r}=e.data||{};switch(t){case"RECUR_ELEMENTS_READY":this.sessionId=r.sessionId,this.timestamp=r.timestamp,this.creditToken=r.creditToken,this.emit("ready",r);break;case"RECUR_CARD_VALID":this.emit("change",{valid:r.valid});break;case"RECUR_CARD_TOKENIZED":this.cardToken=r.cardToken,this.cardTimestamp=r.timestamp,this.emit("tokenized",r);break;case"RECUR_PAYMENT_ERROR":this.emit("error",r);break;case"RECUR_RESIZE":this.iframe&&r?.height&&(this.iframe.style.height=`${r.height}px`);break}}isValidOrigin(e){try{let t=new URL(this.embedUrl).origin;return e===t}catch{return!1}}async tokenize(){if(!this.iframe||!this.iframe.contentWindow)throw new Error("Elements not mounted");let e=new URL(this.embedUrl).origin;return this.iframe.contentWindow.postMessage({type:"RECUR_TOKENIZE"},e),new Promise((t,r)=>{let i=setTimeout(()=>{r(new Error("Tokenization timeout"))},6e4),s=o=>{clearTimeout(i),this.off("tokenized",s),t(o)},a=o=>{clearTimeout(i),this.off("error",a),r(new Error(o.message||"Tokenization failed"))};this.on("tokenized",s),this.on("error",a)})}async confirmPayment(e){if(!this.sessionId||!this.cardToken)throw new Error("Card not tokenized. Call tokenize() first.");let t=await fetch(`${this.baseUrl}/api/v1/elements/confirm`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.publishableKey},body:JSON.stringify({sessionId:this.sessionId,sdkToken:this.cardToken,timestamp:this.cardTimestamp,creditToken:this.creditToken,productId:e.productId,email:e.email,name:e.name,phone:e.phone,metadata:e.metadata})}),r=await t.json();return t.ok?r:{status:"failed",message:r.error||r.message||"Payment failed",canRetry:r.canRetry??!0}}getDefaultBaseUrl(){if(typeof window>"u")return"https://app.recur.tw";let e=window.location.hostname;return e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1"?`${window.location.protocol}//${e}:3000`:"https://app.recur.tw"}getDefaultEmbedUrl(){if(typeof window>"u")return"https://embed.recur.tw";let e=window.location.hostname;return e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1"?`${window.location.protocol}//${e}:3002`:"https://embed.recur.tw"}destroy(){this.iframe&&this.iframe.parentNode&&this.iframe.parentNode.removeChild(this.iframe),this.iframe=null,this.container=null,this.sessionId=null,this.timestamp=null,this.creditToken=null,this.cardToken=null,this.cardTimestamp=null,this.eventHandlers.clear(),window.removeEventListener("message",this.handleMessage.bind(this))}};function _(l){return new h(l)}var y=class{constructor(e){n(this,"core");n(this,"currentModal",null);n(this,"currentIframe",null);this.core=new L(e)}async fetchPlans(){return await this.core.fetchPlans()}async createEmbeddedCheckout(e){let t=this.core.getConfig();await new z(t,e).render()}async redirectToCheckout(e){let t=this.core.getConfig(),r=()=>{if(typeof window<"u"){let c=window.location.hostname;if(c==="localhost"||c.includes(".test")||c.includes(".local")||c==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"},i=t.baseUrl||r(),s={productId:e.productId,successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail);let a=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!a.ok){let c=await a.json().catch(()=>({}));throw new Error(c.error?.message||"Failed to create checkout session")}let o=await a.json();window.location.href=o.url}async createCheckoutSession(e){let t=this.core.getConfig(),r=()=>{if(typeof window<"u"){let o=window.location.hostname;if(o==="localhost"||o.includes(".test")||o.includes(".local")||o==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"},i=t.baseUrl||r(),s={productId:e.productId,successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail);let a=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!a.ok){let o=await a.json().catch(()=>({}));throw new Error(o.error?.message||"Failed to create checkout session")}return a.json()}async checkout(e){try{let t=await this.core.createSubscription(e);e.onSuccess&&e.onSuccess(t);let r=this.core.getConfig(),i=e.mode||"redirect";if(r.mockMode)console.log("[Recur SDK] \u{1F3AD} Mock mode: Showing mock payment UI"),await this.showMockPaymentUI(i,t,e.container,e.onClose);else{let a=`${r.baseUrl||window.location.origin}/checkout/${t.subscription.id}`;switch(i){case"modal":this.openModal(a,e.onClose);break;case"iframe":this.embedIframe(a,e.container,e.onClose);break;case"redirect":default:window.location.href=a;break}}}catch(t){if(e.onError)e.onError(t);else throw console.error("Recur checkout error:",t),t}}openModal(e,t){this.closeModal(),this.currentModal=new R(()=>{this.currentModal=null,t&&t()}),this.currentModal.open(e)}embedIframe(e,t,r){if(!t)throw new Error("Container is required for iframe mode");this.removeIframe(),this.currentIframe=new P(t,()=>{this.currentIframe=null,r&&r()}),this.currentIframe.embed(e)}closeModal(){this.currentModal&&(this.currentModal.close(),this.currentModal=null)}removeIframe(){this.currentIframe&&(this.currentIframe.remove(),this.currentIframe=null)}close(){this.closeModal(),this.removeIframe()}async showMockPaymentUI(e,t,r,i){let s=this.generateMockPaymentHTML(t);switch(e){case"modal":this.showMockModal(s,i);break;case"iframe":this.showMockIframe(s,r,i);break;case"redirect":default:let o=`${window.location.origin}/checkout/${t.subscription.id}`;console.log("[Recur SDK] \u{1F3AD} Mock mode: Would redirect to:",o);let{RecurToast:c}=await Promise.resolve().then(()=>(g(),b));c.show("\u{1F3AD} Mock \u6A21\u5F0F\uFF1A\u5728\u771F\u5BE6\u74B0\u5883\u4E2D\uFF0C\u7528\u6236\u6703\u88AB\u5C0E\u5411\u4ED8\u6B3E\u9801\u9762","info",8e3),console.log("Payment URL:",o);break}}generateMockPaymentHTML(e){return`
1383
- <!DOCTYPE html>
1384
- <html>
1385
- <head>
1386
- <meta charset="UTF-8">
1387
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
1388
- <style>
1389
- body {
1390
- margin: 0;
1391
- padding: 20px;
1392
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1393
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1394
- min-height: 100vh;
1395
- display: flex;
1396
- align-items: center;
1397
- justify-content: center;
1398
- }
1399
- .container {
1400
- background: white;
1401
- border-radius: 12px;
1402
- padding: 40px;
1403
- max-width: 500px;
1404
- width: 100%;
1405
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
1406
- }
1407
- .badge {
1408
- display: inline-block;
1409
- padding: 4px 12px;
1410
- background: #fed7d7;
1411
- color: #c53030;
1412
- border-radius: 12px;
1413
- font-size: 12px;
1414
- font-weight: 600;
1415
- margin-bottom: 20px;
1416
- border: 2px solid #fc8181;
1417
- }
1418
- h1 {
1419
- color: #1a202c;
1420
- margin-bottom: 24px;
1421
- font-size: 24px;
1422
- }
1423
- .info {
1424
- background: #f7fafc;
1425
- border-radius: 8px;
1426
- padding: 16px;
1427
- margin-bottom: 24px;
1428
- }
1429
- .info-row {
1430
- display: flex;
1431
- justify-content: space-between;
1432
- padding: 8px 0;
1433
- border-bottom: 1px solid #e2e8f0;
1434
- }
1435
- .info-row:last-child {
1436
- border-bottom: none;
1437
- }
1438
- .label {
1439
- color: #718096;
1440
- font-size: 14px;
1441
- }
1442
- .value {
1443
- color: #2d3748;
1444
- font-weight: 500;
1445
- font-size: 14px;
1446
- }
1447
- .card-form {
1448
- margin-bottom: 24px;
1449
- }
1450
- .form-group {
1451
- margin-bottom: 16px;
1452
- }
1453
- label {
1454
- display: block;
1455
- margin-bottom: 8px;
1456
- color: #2d3748;
1457
- font-weight: 500;
1458
- font-size: 14px;
1459
- }
1460
- .mock-input {
1461
- width: 100%;
1462
- padding: 12px 16px;
1463
- border: 2px solid #e2e8f0;
1464
- border-radius: 8px;
1465
- background: #f7fafc;
1466
- color: #6b7280;
1467
- font-size: 14px;
1468
- }
1469
- button {
1470
- width: 100%;
1471
- padding: 14px;
1472
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1473
- color: white;
1474
- border: none;
1475
- border-radius: 8px;
1476
- font-size: 16px;
1477
- font-weight: 600;
1478
- cursor: pointer;
1479
- }
1480
- button:hover {
1481
- opacity: 0.9;
1482
- }
1483
- .note {
1484
- margin-top: 16px;
1485
- padding: 12px;
1486
- background: #fef5e7;
1487
- border-left: 4px solid #f59e0b;
1488
- border-radius: 4px;
1489
- font-size: 13px;
1490
- color: #78350f;
1491
- }
1492
- </style>
1493
- </head>
1494
- <body>
1495
- <div class="container">
1496
- <span class="badge">\u{1F3AD} MOCK MODE</span>
1497
- <h1>\u8A02\u95B1\u4ED8\u6B3E\uFF08\u6A21\u64EC\uFF09</h1>
1498
-
1499
- <div class="info">
1500
- <div class="info-row">
1501
- <span class="label">\u65B9\u6848</span>
1502
- <span class="value">${e.subscription.planName}</span>
1503
- </div>
1504
- <div class="info-row">
1505
- <span class="label">\u91D1\u984D</span>
1506
- <span class="value">NT$ ${e.subscription.amount}</span>
1507
- </div>
1508
- <div class="info-row">
1509
- <span class="label">\u9031\u671F</span>
1510
- <span class="value">${e.subscription.billingPeriod}</span>
1511
- </div>
1512
- <div class="info-row">
1513
- <span class="label">\u8A66\u7528\u671F</span>
1514
- <span class="value">${e.subscription.trialDays} \u5929</span>
1515
- </div>
1516
- </div>
1517
-
1518
- <div class="card-form">
1519
- <div class="form-group">
1520
- <label>\u4FE1\u7528\u5361\u865F</label>
1521
- <input type="text" class="mock-input" value="4242 4242 4242 4242 (Mock)" readonly>
1522
- </div>
1523
- <div class="form-group">
1524
- <label>\u6709\u6548\u671F\u9650</label>
1525
- <input type="text" class="mock-input" value="12 / 25 (Mock)" readonly>
1526
- </div>
1527
- <div class="form-group">
1528
- <label>\u5B89\u5168\u78BC</label>
1529
- <input type="text" class="mock-input" value="123 (Mock)" readonly>
1530
- </div>
1531
- </div>
1532
-
1533
- <button onclick="handleMockPayment()">\u78BA\u8A8D\u4ED8\u6B3E\uFF08\u6A21\u64EC\uFF09</button>
1534
-
1535
- <div class="note">
1536
- <strong>\u{1F3AD} Mock \u6A21\u5F0F\u8AAA\u660E</strong><br>
1537
- \u9019\u662F\u6A21\u64EC\u7684\u4ED8\u6B3E\u8868\u55AE\u3002\u9EDE\u64CA\u300C\u78BA\u8A8D\u4ED8\u6B3E\u300D\u6703\u6A21\u64EC\u6210\u529F\u7684\u652F\u4ED8\u6D41\u7A0B\u3002
1538
- </div>
1539
- </div>
1540
-
1541
- <script>
1542
- function handleMockPayment() {
1543
- console.log('\u{1F3AD} Mock \u6A21\u5F0F\uFF1A\u4ED8\u6B3E\u6210\u529F\uFF01');
1544
-
1545
- // Notify parent to show toast
1546
- if (window.parent !== window) {
1547
- window.parent.postMessage({
1548
- type: 'recur-mock-payment-success',
1549
- showToast: {
1550
- message: '\u{1F3AD} Mock \u6A21\u5F0F\uFF1A\u4ED8\u6B3E\u6210\u529F\uFF01\u5728\u771F\u5BE6\u74B0\u5883\u4E2D\u6703\u89F8\u767C\u5BE6\u969B\u7684\u652F\u4ED8\u8655\u7406',
1551
- type: 'success'
1552
- }
1553
- }, '*');
1554
- } else {
1555
- // If not in iframe, show toast directly
1556
- console.log('Mock payment successful');
1557
- }
1558
- }
1559
- </script>
1560
- </body>
1561
- </html>
1562
- `}showMockModal(e,t){this.closeModal();let r=document.createElement("div");r.id="recur-mock-modal",r.style.cssText=`
1419
+ `.replace(/\s+/g," ").trim(),this.iframe.allow="payment *",this.iframe.setAttribute("title","Secure payment input frame"),this.iframe.setAttribute("role","presentation"),this.iframe.setAttribute("scrolling","no"),this.iframe.setAttribute("frameBorder","0"),this.container.innerHTML="",this.container.appendChild(this.iframe),new Promise((r,i)=>{let s=setTimeout(()=>{i(new Error("Elements initialization timeout"))},3e4),n=()=>{clearTimeout(s),this.off("ready",n),r()},o=l=>{clearTimeout(s),this.off("error",o),i(new Error(l.message||"Elements initialization failed"))};this.on("ready",n),this.on("error",o)})}on(e,t){this.eventHandlers.has(e)||this.eventHandlers.set(e,new Set),this.eventHandlers.get(e).add(t)}off(e,t){let r=this.eventHandlers.get(e);r&&r.delete(t)}emit(e,t){let r=this.eventHandlers.get(e);r&&r.forEach(i=>i(t))}handleMessage(e){if(!this.isValidOrigin(e.origin))return;let{type:t,data:r}=e.data||{};switch(t){case"RECUR_ELEMENTS_READY":this.sessionId=r.sessionId,this.timestamp=r.timestamp,this.creditToken=r.creditToken,this.emit("ready",r);break;case"RECUR_CARD_VALID":this.emit("change",{valid:r.valid});break;case"RECUR_CARD_TOKENIZED":this.cardToken=r.cardToken,this.cardTimestamp=r.timestamp,this.emit("tokenized",r);break;case"RECUR_PAYMENT_ERROR":this.emit("error",r);break;case"RECUR_RESIZE":this.iframe&&r?.height&&(this.iframe.style.height=`${r.height}px`);break}}isValidOrigin(e){try{let t=new URL(this.embedUrl).origin;return e===t}catch{return!1}}async tokenize(){if(!this.iframe||!this.iframe.contentWindow)throw new Error("Elements not mounted");let e=new URL(this.embedUrl).origin;return this.iframe.contentWindow.postMessage({type:"RECUR_TOKENIZE"},e),new Promise((t,r)=>{let i=setTimeout(()=>{r(new Error("Tokenization timeout"))},6e4),s=o=>{clearTimeout(i),this.off("tokenized",s),t(o)},n=o=>{clearTimeout(i),this.off("error",n),r(new Error(o.message||"Tokenization failed"))};this.on("tokenized",s),this.on("error",n)})}async confirmPayment(e){if(!this.sessionId||!this.cardToken)throw new Error("Card not tokenized. Call tokenize() first.");let t=await fetch(`${this.baseUrl}/api/v1/elements/confirm`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.publishableKey},body:JSON.stringify({sessionId:this.sessionId,sdkToken:this.cardToken,timestamp:this.cardTimestamp,creditToken:this.creditToken,productId:e.productId,email:e.email,name:e.name,phone:e.phone,metadata:e.metadata})}),r=await t.json();return t.ok?r:{status:"failed",message:r.error||r.message||"Payment failed",canRetry:r.canRetry??!0}}getDefaultBaseUrl(){if(typeof window>"u")return"https://app.recur.tw";let e=window.location.hostname;return e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1"?`${window.location.protocol}//${e}:3000`:"https://app.recur.tw"}getDefaultEmbedUrl(){if(typeof window>"u")return"https://embed.recur.tw";let e=window.location.hostname;return e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1"?`${window.location.protocol}//${e}:3002`:"https://embed.recur.tw"}destroy(){this.iframe&&this.iframe.parentNode&&this.iframe.parentNode.removeChild(this.iframe),this.iframe=null,this.container=null,this.sessionId=null,this.timestamp=null,this.creditToken=null,this.cardToken=null,this.cardTimestamp=null,this.eventHandlers.clear(),window.removeEventListener("message",this.handleMessage.bind(this))}};function $(c){return new v(c)}var fe="https://vendor.payuni.com.tw/sdk/uni-payment.js",be="https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",te=!1,D=!1,x=null;async function re(c=!1){return te&&window.UniPayment?Promise.resolve():(D&&x||(D=!0,x=new Promise((e,t)=>{let r=document.createElement("script");r.src=c?be:fe,r.async=!0,r.onload=()=>{te=!0,D=!1,e()},r.onerror=()=>{D=!1,x=null,t(new Error("Failed to load PAYUNi SDK"))},document.head.appendChild(r)})),x)}var w=class{constructor(e){a(this,"core");a(this,"currentModal",null);a(this,"currentIframe",null);a(this,"currentModalOverlay",null);this.core=new z(e)}async fetchPlans(){return await this.core.fetchPlans()}async createEmbeddedCheckout(e){let t=this.core.getConfig();await new _(t,e).render()}async redirectToCheckout(e){let t=this.core.getConfig(),r=()=>{if(typeof window<"u"){let l=window.location.hostname;if(l==="localhost"||l.includes(".test")||l.includes(".local")||l==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"},i=t.baseUrl||r(),s={productId:e.productId,successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail);let n=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!n.ok){let l=await n.json().catch(()=>({}));throw new Error(l.error?.message||"Failed to create checkout session")}let o=await n.json();window.location.href=o.url}async createCheckoutSession(e){let t=this.core.getConfig(),r=()=>{if(typeof window<"u"){let o=window.location.hostname;if(o==="localhost"||o.includes(".test")||o.includes(".local")||o==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"},i=t.baseUrl||r(),s={productId:e.productId,successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail);let n=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!n.ok){let o=await n.json().catch(()=>({}));throw new Error(o.error?.message||"Failed to create checkout session")}return n.json()}async checkout(e){let t=this.core.getConfig(),r=null;try{if(console.log("[Recur SDK] Starting checkout flow...",{planId:e.planId,mode:e.mode}),!e.planId)throw new Error("planId is required");if(!t.publishableKey)throw new Error("publishableKey is required");if(!e.customerEmail||!e.customerName)throw new Error("customerEmail and customerName are required");let i=this.getBaseUrl();console.log("[Recur SDK] Base URL:",i);let s={"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},n=e.mode||"modal",o=null;if(n==="modal"){let u=this.createModalWithSkeleton(e.onClose);r=u.overlay,o=u.container}else if(n==="iframe"){if(o=this.getEmbeddedContainer(e.container),!o)throw new Error("Container is required for iframe mode");o.innerHTML="";let u=document.createElement("recur-payment-form-skeleton");o.appendChild(u)}console.log("[Recur SDK] Step 1: Creating checkout session...");let l=await fetch(`${i}/v1/checkouts`,{method:"POST",headers:s,body:JSON.stringify({productId:e.planId,customerName:e.customerName,customerEmail:e.customerEmail,customerPhone:e.customerPhone})});if(!l.ok){let u=await l.json().catch(()=>({}));console.error("[Recur SDK] Failed to create checkout:",u);let A=u.details||u.error||"Failed to create checkout";throw new Error(A)}let d=await l.json();if(console.log("[Recur SDK] Checkout created successfully:",d),e.onSuccess?.(d),n==="redirect"){let u=`https://checkout.recur.tw/${d.checkout.id}`;console.log("[Recur SDK] Redirecting to hosted checkout:",u),window.location.href=u;return}if(console.log("[Recur SDK] Step 2: Extracting SDK token..."),!d.sdkToken)throw new Error("SDK token missing from checkout response");console.log("[Recur SDK] Step 3: Loading PAYUNi SDK...");let y=!0;if(await re(y),console.log("[Recur SDK] PAYUNi SDK loaded successfully"),!window.UniPayment)throw new Error("PAYUNi SDK failed to load");if(console.log("[Recur SDK] Step 4: Rendering payment form..."),!o)throw new Error("Payment container not available");o.innerHTML="";let m=document.createElement("recur-payment-form");if(m.setAttribute("container-id",o.id||"recur-payment-container"),e.customerName&&m.setAttribute("customer-name",e.customerName),e.customerEmail&&m.setAttribute("customer-email",e.customerEmail),d.plan?.name&&m.setAttribute("plan-name",d.plan.name),d.checkout?.amount&&m.setAttribute("amount",d.checkout.amount.toString()),d.plan?.billingPeriod&&m.setAttribute("billing-period",d.plan.billingPeriod),m.setAttribute("custom-styles",`
1420
+ .form-input-focus {
1421
+ border-color: var(--ring, hsl(215 16% 47%)) !important;
1422
+ outline: 0 !important;
1423
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring, hsl(215 16% 47%)) 50%, transparent) !important;
1424
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out !important;
1425
+ }
1426
+ `),o.appendChild(m),await new Promise(u=>setTimeout(u,100)),console.log("[Recur SDK] Step 5: Initializing PAYUNi SDK..."),await m.initializePayment(d.sdkToken,y?"SANDBOX":"PRODUCTION")===null){console.log("[Recur SDK] Initialization aborted");return}console.log("[Recur SDK] PAYUNi SDK initialized successfully"),console.log("[Recur SDK] Step 6: Setting up submit handler..."),m.addEventListener("submit",(async u=>{console.log("[Recur SDK] Form submitted");let A=u,{paymentSession:se}=A.detail;try{let b=await se.getTradeResult();console.log("[Recur SDK] Trade result received"),console.log("[Recur SDK] Executing payment...");let E=b.EncryptInfo||b.creditToken,oe=b.HashTimestamp||b.timestamp;if(!E)throw new Error("Missing payment token from PAYUNi SDK");let ne=d.checkout.productType==="SUBSCRIPTION"?{creditToken:E,timestamp:oe}:{},H=await fetch(`${i}/v1/checkouts/${d.checkout.id}/pay`,{method:"POST",headers:s,body:JSON.stringify(ne)});if(!H.ok){let ae=await H.json().catch(()=>({}));throw new Error(ae.error||"Failed to execute payment")}let p=await H.json();if(console.log("[Recur SDK] Payment executed:",p),p.requires3D&&p.redirectUrl){console.log("[Recur SDK] 3D verification required"),window.location.href=p.redirectUrl;return}e.onPaymentComplete&&(p.subscription?e.onPaymentComplete({id:p.subscription.id,status:p.subscription.status,planId:d.checkout.productId,amount:d.checkout.amount,billingPeriod:p.subscription.billingPeriod,currentPeriodStart:p.subscription.currentPeriodStart,currentPeriodEnd:p.subscription.currentPeriodEnd}):e.onPaymentComplete({id:p.checkout.id,status:p.checkout.status,planId:d.checkout.productId,amount:d.checkout.amount,billingPeriod:d.checkout.productType})),console.log("[Recur SDK] Checkout flow completed successfully!"),m.resetButton?.(),r&&r.remove()}catch(b){console.error("[Recur SDK] Payment error:",b);let E={code:"PAYMENT_FAILED",message:b instanceof Error?b.message:"Payment failed"};e.onError?.(E),m.resetButton?.()}})),console.log("[Recur SDK] Checkout flow initialized, waiting for user input...")}catch(i){console.error("[Recur SDK] Checkout error:",i),r&&r.remove();let s={code:"CHECKOUT_ERROR",message:i instanceof Error?i.message:"An unknown error occurred"};throw e.onError?.(s),i}}getBaseUrl(){let e=this.core.getConfig();if(e.baseUrl)return e.baseUrl;if(typeof window<"u"){let t=window.location.hostname;if(t==="localhost"||t.includes(".test")||t.includes(".local")||t==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}createModalWithSkeleton(e){this.closeModal();let t=document.createElement("div");t.id="recur-modal-overlay",t.style.cssText=`
1563
1427
  position: fixed;
1564
1428
  top: 0;
1565
1429
  left: 0;
1566
- right: 0;
1567
- bottom: 0;
1430
+ width: 100%;
1431
+ height: 100%;
1568
1432
  background: rgba(0, 0, 0, 0.5);
1569
1433
  display: flex;
1570
1434
  align-items: center;
1571
1435
  justify-content: center;
1572
- z-index: 999999;
1573
- `;let i=document.createElement("div");i.style.cssText=`
1436
+ z-index: 9999;
1437
+ `;let r=document.createElement("div");r.style.cssText=`
1438
+ max-width: 500px;
1574
1439
  width: 90%;
1575
- max-width: 600px;
1576
- height: 80%;
1577
- max-height: 700px;
1578
- background: white;
1579
- border-radius: 12px;
1580
- overflow: hidden;
1440
+ max-height: 90vh;
1441
+ overflow-y: auto;
1581
1442
  position: relative;
1582
- `;let s=document.createElement("button");s.textContent="\u2715",s.style.cssText=`
1443
+ `;let i=document.createElement("button");i.innerHTML="\u2715",i.style.cssText=`
1583
1444
  position: absolute;
1584
- top: 16px;
1585
- right: 16px;
1586
- background: white;
1445
+ top: 12px;
1446
+ right: 12px;
1447
+ background: rgba(0, 0, 0, 0.05);
1587
1448
  border: none;
1449
+ font-size: 18px;
1450
+ cursor: pointer;
1451
+ color: #666;
1452
+ padding: 0;
1588
1453
  width: 32px;
1589
1454
  height: 32px;
1455
+ display: flex;
1456
+ align-items: center;
1457
+ justify-content: center;
1590
1458
  border-radius: 50%;
1591
- cursor: pointer;
1592
- font-size: 18px;
1593
- z-index: 1;
1594
- box-shadow: 0 2px 8px rgba(0,0,0,0.15);
1595
- `,s.onclick=()=>{r.remove(),t&&t()};let a=document.createElement("iframe");a.style.cssText="width: 100%; height: 100%; border: none;",a.srcdoc=e,i.appendChild(s),i.appendChild(a),r.appendChild(i),document.body.appendChild(r),window.addEventListener("message",async o=>{if(o.data.type==="recur-mock-payment-success"){if(o.data.showToast){let{RecurToast:c}=await Promise.resolve().then(()=>(g(),b));c.show(o.data.showToast.message,o.data.showToast.type||"success",5e3)}r.remove(),t&&t()}})}showMockIframe(e,t,r){if(!t)throw new Error("Container is required for iframe mode");let i=typeof t=="string"?document.getElementById(t)||document.querySelector(t):t;if(!i)throw new Error("Container element not found");i.innerHTML="";let s=document.createElement("iframe");s.style.cssText="width: 100%; height: 100%; border: none; min-height: 600px;",s.srcdoc=e,i.appendChild(s),window.addEventListener("message",async a=>{if(a.data.type==="recur-mock-payment-success"){if(a.data.showToast){let{RecurToast:o}=await Promise.resolve().then(()=>(g(),b));o.show(a.data.showToast.message,a.data.showToast.type||"success",5e3)}r&&r()}})}};function X(l){return new y(l)}var re={init:X,RecurCheckout:y,RecurElements:h,createElements:_};return ee(ie);})();
1459
+ z-index: 10;
1460
+ transition: background 0.2s;
1461
+ `,i.onmouseover=()=>{i.style.background="rgba(0, 0, 0, 0.1)"},i.onmouseout=()=>{i.style.background="rgba(0, 0, 0, 0.05)"},i.onclick=()=>{t.remove(),e?.()};let s=document.createElement("div");s.id="recur-modal-payment-container",s.style.cssText=`
1462
+ background: white;
1463
+ border-radius: 12px;
1464
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
1465
+ `;let n=document.createElement("recur-payment-form-skeleton");return s.appendChild(n),r.appendChild(i),r.appendChild(s),t.appendChild(r),document.body.appendChild(t),this.currentModalOverlay=t,{overlay:t,container:s}}getEmbeddedContainer(e){return e?typeof e=="string"?document.getElementById(e)||document.querySelector(e):e:null}closeModal(){this.currentModal&&(this.currentModal.close(),this.currentModal=null),this.currentModalOverlay&&(this.currentModalOverlay.remove(),this.currentModalOverlay=null)}removeIframe(){this.currentIframe&&(this.currentIframe.remove(),this.currentIframe=null)}close(){this.closeModal(),this.removeIframe()}};function ie(c){return new w(c)}var ge={init:ie,RecurCheckout:w,RecurElements:v,createElements:$};return pe(ye);})();
1596
1466
  if (typeof window !== "undefined") {
1597
1467
  window.RecurCheckout = RecurCheckout.default;
1598
1468
  window.RecurElements = RecurCheckout.RecurElements;