recur-tw 0.13.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/checkout.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var RecurCheckoutScript=(()=>{var f=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var R=(e,t)=>{for(var r in t)f(e,r,{get:t[r],enumerable:!0})},_=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of E(t))!C.call(e,n)&&n!==r&&f(e,n,{get:()=>t[n],enumerable:!(o=v(t,n))||o.enumerable});return e};var U=e=>_(f({},"__esModule",{value:!0}),e);var T={};R(T,{default:()=>I});var a={embedUrl:"https://embed.recur.tw",apiUrl:"https://api.recur.tw"},h=null,p=null;function m(){if(document.getElementById("recur-checkout-styles"))return;let e=document.createElement("style");e.id="recur-checkout-styles",e.textContent=`
1
+ "use strict";var RecurCheckoutScript=(()=>{var f=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var R=(e,t)=>{for(var r in t)f(e,r,{get:t[r],enumerable:!0})},_=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of E(t))!C.call(e,o)&&o!==r&&f(e,o,{get:()=>t[o],enumerable:!(n=v(t,o))||n.enumerable});return e};var U=e=>_(f({},"__esModule",{value:!0}),e);var T={};R(T,{default:()=>I});var s={embedUrl:"https://embed.recur.tw",apiUrl:"https://api.recur.tw"},h=null,p=null;function m(){if(document.getElementById("recur-checkout-styles"))return;let e=document.createElement("style");e.id="recur-checkout-styles",e.textContent=`
2
2
  .recur-checkout-dialog {
3
3
  border: none;
4
4
  border-radius: 12px;
@@ -37,6 +37,14 @@
37
37
  }
38
38
  }
39
39
 
40
+ .recur-checkout-dialog__content {
41
+ display: flex;
42
+ flex-direction: column;
43
+ width: 100%;
44
+ height: 100%;
45
+ outline: none;
46
+ }
47
+
40
48
  .recur-checkout-dialog__header {
41
49
  display: flex;
42
50
  justify-content: flex-end;
@@ -122,5 +130,5 @@
122
130
  opacity: 0.7;
123
131
  pointer-events: none;
124
132
  }
125
- `,document.head.appendChild(e)}function S(e){try{let r=new URL(e,window.location.origin).pathname.split("/"),o=r.indexOf("buy");if(o===-1||o>=r.length-1)return null;let n=r[o+1];return n?n.startsWith("prod_")?{productId:n}:{productSlug:n}:null}catch{return null}}function P(e){let t=e.getAttribute("data-key");if(t)return t;try{let n=e.getAttribute("href");if(n){let s=new URL(n,window.location.origin).searchParams.get("key");if(s)return s}}catch{}let r=document.querySelector("script[data-recur-key]");if(r)return r.getAttribute("data-recur-key");let o=window.RecurConfig;return o?.publishableKey?o.publishableKey:null}async function b(e,t){let r={};e.productId&&(r.productId=e.productId),e.email&&(r.customerEmail=e.email),e.name&&(r.customerName=e.name);let o=await fetch(`${a.apiUrl}/v1/checkouts`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t,"X-Recur-Embed-Domain":a.embedUrl,"X-Recur-SDK-Type":"checkout.js","X-Recur-Source":window.location.origin},body:JSON.stringify(r)});if(!o.ok){let i=await o.json().catch(()=>({}));throw new Error(i.error?.message||i.error||"Failed to create checkout")}let n=await o.json();return{id:n.checkout.id,publishableKey:t,clientSecret:n.checkout.client_secret}}function y(e,t){u(),m();let r=document.createElement("dialog");r.className="recur-checkout-dialog";let o=document.createElement("div");o.className="recur-checkout-dialog__header";let n=document.createElement("button");n.className="recur-checkout-dialog__close",n.innerHTML="×",n.type="button",n.setAttribute("aria-label","Close"),n.onclick=()=>{u(),t?.(),d("recur:close",{})},o.appendChild(n);let i=document.createElement("iframe");i.className="recur-checkout-dialog__iframe",i.src=e,i.setAttribute("allow","payment"),i.setAttribute("title","Recur Checkout"),r.appendChild(o),r.appendChild(i),document.body.appendChild(r),h=r,p=i,r.showModal(),document.body.style.overflow="hidden",r.addEventListener("cancel",s=>{s.preventDefault(),u(),t?.(),d("recur:close",{})}),window.addEventListener("message",k)}function u(){h&&(h.close(),h.remove(),h=null),p=null,document.body.style.overflow="",window.removeEventListener("message",k)}function k(e){if(!e.origin.includes("recur.tw")&&!e.origin.includes("localhost"))return;let{type:t,data:r}=e.data||{};switch(t){case"RECUR_PAYMENT_SUCCESS":u(),d("recur:success",r);break;case"RECUR_PAYMENT_ERROR":d("recur:error",r);break;case"RECUR_PAYMENT_CANCEL":u(),d("recur:close",{});break;case"RECUR_RESIZE":p&&r?.height&&(p.style.height=`${Math.min(r.height+56,window.innerHeight*.9)}px`);break}}function d(e,t){window.dispatchEvent(new CustomEvent(e,{detail:t}))}async function A(e,t){e.preventDefault();let r=t.getAttribute("href");if(!r){console.error("[Recur] Missing href on recur-button");return}let o=S(r);if(!o){console.error("[Recur] Invalid product URL:",r);return}let n=P(t);if(!n){console.error("[Recur] Missing publishable key. Add data-key attribute or set RecurConfig.publishableKey");return}let i={productId:o.productId||"",email:t.getAttribute("data-email")||void 0,name:t.getAttribute("data-name")||void 0,successUrl:t.getAttribute("data-success-url")||void 0,theme:t.getAttribute("data-theme")||void 0};t.setAttribute("data-loading","true");let s=t.textContent;t.textContent="...";try{let c=await b(i,n),l=new URL(`${a.embedUrl}/checkout`);l.searchParams.set("id",c.id),l.searchParams.set("key",c.publishableKey),l.searchParams.set("client_secret",c.clientSecret),i.theme&&l.searchParams.set("theme",i.theme),y(l.toString(),()=>{let x=i.successUrl})}catch(c){console.error("[Recur] Checkout error:",c),d("recur:error",{message:c instanceof Error?c.message:"Unknown error"})}finally{t.setAttribute("data-loading","false"),t.textContent=s}}function g(){document.querySelectorAll(".recur-button").forEach(t=>{t.hasAttribute("data-recur-initialized")||(t.setAttribute("data-recur-initialized","true"),t.addEventListener("click",r=>A(r,t)))})}function L(){let e=window.location.hostname;(e==="localhost"||e==="127.0.0.1"||e.includes(".local"))&&(a.embedUrl=`${window.location.protocol}//${e}:3002`,a.apiUrl=`${window.location.protocol}//${e}:3000/api`)}var w={config(e){Object.assign(a,e)},async popup(e){let t=await b(e,e.key),r=new URL(`${a.embedUrl}/checkout`);r.searchParams.set("id",t.id),r.searchParams.set("key",t.publishableKey),r.searchParams.set("client_secret",t.clientSecret),e.theme&&r.searchParams.set("theme",e.theme),y(r.toString())},close(){u()},init(){g()}};function M(){L(),m(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",g):g(),new MutationObserver(t=>{for(let r of t)r.addedNodes.length>0&&g()}).observe(document.body,{childList:!0,subtree:!0})}window.Recur=w;M();var I=w;return U(T);})();
133
+ `,document.head.appendChild(e)}function A(e){try{let r=new URL(e,window.location.origin).pathname.split("/"),n=r.indexOf("buy");if(n===-1||n>=r.length-1)return null;let o=r[n+1];return o?o.startsWith("prod_")?{productId:o}:{productSlug:o}:null}catch{return null}}function S(e){let t=e.getAttribute("data-key");if(t)return t;try{let o=e.getAttribute("href");if(o){let c=new URL(o,window.location.origin).searchParams.get("key");if(c)return c}}catch{}let r=document.querySelector("script[data-recur-key]");if(r)return r.getAttribute("data-recur-key");let n=window.RecurConfig;return n?.publishableKey?n.publishableKey:null}async function b(e,t){let r={};e.productId&&(r.productId=e.productId),e.email&&(r.customerEmail=e.email),e.name&&(r.customerName=e.name);let n=await fetch(`${s.apiUrl}/v1/checkouts`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t,"X-Recur-Embed-Domain":s.embedUrl,"X-Recur-SDK-Type":"checkout.js","X-Recur-Source":window.location.origin},body:JSON.stringify(r)});if(!n.ok){let i=await n.json().catch(()=>({}));throw new Error(i.error?.message||i.error||"Failed to create checkout")}let o=await n.json();return{id:o.checkout.id,publishableKey:t,clientSecret:o.checkout.client_secret}}function y(e,t){u(),m();let r=document.createElement("dialog");r.className="recur-checkout-dialog";let n=document.createElement("div");n.className="recur-checkout-dialog__content",n.setAttribute("tabindex","-1"),n.setAttribute("autofocus","");let o=document.createElement("div");o.className="recur-checkout-dialog__header";let i=document.createElement("button");i.className="recur-checkout-dialog__close",i.innerHTML="×",i.type="button",i.setAttribute("aria-label","Close"),i.onclick=()=>{u(),t?.(),d("recur:close",{})},o.appendChild(i);let c=document.createElement("iframe");c.className="recur-checkout-dialog__iframe",c.src=e,c.setAttribute("allow","payment"),c.setAttribute("title","Recur Checkout"),n.appendChild(o),n.appendChild(c),r.appendChild(n),document.body.appendChild(r),h=r,p=c,r.showModal(),document.body.style.overflow="hidden",r.addEventListener("cancel",a=>{a.preventDefault(),u(),t?.(),d("recur:close",{})}),window.addEventListener("message",k)}function u(){h&&(h.close(),h.remove(),h=null),p=null,document.body.style.overflow="",window.removeEventListener("message",k)}function k(e){if(!e.origin.includes("recur.tw")&&!e.origin.includes("localhost"))return;let{type:t,data:r}=e.data||{};switch(t){case"RECUR_PAYMENT_SUCCESS":u(),d("recur:success",r);break;case"RECUR_PAYMENT_ERROR":d("recur:error",r);break;case"RECUR_PAYMENT_CANCEL":u(),d("recur:close",{});break;case"RECUR_RESIZE":p&&r?.height&&(p.style.height=`${Math.min(r.height+56,window.innerHeight*.9)}px`);break}}function d(e,t){window.dispatchEvent(new CustomEvent(e,{detail:t}))}async function P(e,t){e.preventDefault();let r=t.getAttribute("href");if(!r){console.error("[Recur] Missing href on recur-button");return}let n=A(r);if(!n){console.error("[Recur] Invalid product URL:",r);return}let o=S(t);if(!o){console.error("[Recur] Missing publishable key. Add data-key attribute or set RecurConfig.publishableKey");return}let i={productId:n.productId||"",email:t.getAttribute("data-email")||void 0,name:t.getAttribute("data-name")||void 0,successUrl:t.getAttribute("data-success-url")||void 0,theme:t.getAttribute("data-theme")||void 0};t.setAttribute("data-loading","true");let c=t.textContent;t.textContent="...";try{let a=await b(i,o),l=new URL(`${s.embedUrl}/checkout`);l.searchParams.set("id",a.id),l.searchParams.set("key",a.publishableKey),l.searchParams.set("client_secret",a.clientSecret),i.theme&&l.searchParams.set("theme",i.theme),y(l.toString(),()=>{let x=i.successUrl})}catch(a){console.error("[Recur] Checkout error:",a),d("recur:error",{message:a instanceof Error?a.message:"Unknown error"})}finally{t.setAttribute("data-loading","false"),t.textContent=c}}function g(){document.querySelectorAll(".recur-button").forEach(t=>{t.hasAttribute("data-recur-initialized")||(t.setAttribute("data-recur-initialized","true"),t.addEventListener("click",r=>P(r,t)))})}function L(){let e=window.location.hostname;(e==="localhost"||e==="127.0.0.1"||e.includes(".local"))&&(s.embedUrl=`${window.location.protocol}//${e}:3002`,s.apiUrl=`${window.location.protocol}//${e}:3000/api`)}var w={config(e){Object.assign(s,e)},async popup(e){let t=await b(e,e.key),r=new URL(`${s.embedUrl}/checkout`);r.searchParams.set("id",t.id),r.searchParams.set("key",t.publishableKey),r.searchParams.set("client_secret",t.clientSecret),e.theme&&r.searchParams.set("theme",e.theme),y(r.toString())},close(){u()},init(){g()}};function M(){L(),m(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",g):g(),new MutationObserver(t=>{for(let r of t)r.addedNodes.length>0&&g()}).observe(document.body,{childList:!0,subtree:!0})}window.Recur=w;M();var I=w;return U(T);})();
126
134
  /* Recur Checkout - https://recur.tw */
package/dist/index.cjs CHANGED
@@ -1052,6 +1052,124 @@ var init_payment_form_light = __esm({
1052
1052
  }
1053
1053
  });
1054
1054
 
1055
+ // src/utils/checkout-display.ts
1056
+ function formatZhe(basisPoints) {
1057
+ const zhe = (1e4 - basisPoints) / 1e3;
1058
+ if (Number.isInteger(zhe)) return `${zhe} \u6298`;
1059
+ const zhe10 = zhe * 10;
1060
+ if (Number.isInteger(zhe10)) return `${zhe10} \u6298`;
1061
+ return `${(zhe * 10).toFixed(2)} \u6298`;
1062
+ }
1063
+ function getIntervalText(interval, count) {
1064
+ if (!interval) return "";
1065
+ const countText = count && count > 1 ? count.toString() : "";
1066
+ switch (interval.toUpperCase()) {
1067
+ case "MONTH":
1068
+ return `${countText}\u6708`;
1069
+ case "YEAR":
1070
+ return `${countText}\u5E74`;
1071
+ case "WEEK":
1072
+ return `${countText}\u9031`;
1073
+ case "DAY":
1074
+ return `${countText}\u5929`;
1075
+ default:
1076
+ return "";
1077
+ }
1078
+ }
1079
+ function formatPrice(amount) {
1080
+ return `NT$ ${amount.toLocaleString("zh-TW")}`;
1081
+ }
1082
+ function getCheckoutDiscountDisplay(input) {
1083
+ const {
1084
+ discountType,
1085
+ couponDiscountValue,
1086
+ discountAmount,
1087
+ duration,
1088
+ durationMonths,
1089
+ productPrice,
1090
+ productInterval,
1091
+ productIntervalCount,
1092
+ bonusMonths,
1093
+ bonusTrialDays
1094
+ } = input;
1095
+ const intervalText = getIntervalText(productInterval, productIntervalCount);
1096
+ const originalPriceText = intervalText ? `${formatPrice(productPrice)}/${intervalText}` : formatPrice(productPrice);
1097
+ const bonusSuffix = buildBonusSuffix(bonusMonths, bonusTrialDays);
1098
+ if (discountAmount === 0 && (bonusMonths || bonusTrialDays)) {
1099
+ return {
1100
+ line1: buildPureBonusLine(bonusMonths, bonusTrialDays),
1101
+ line2: null
1102
+ };
1103
+ }
1104
+ if (discountAmount === 0) {
1105
+ return { line1: "", line2: null };
1106
+ }
1107
+ const afterLine = `\u4E4B\u5F8C ${originalPriceText}`;
1108
+ if (discountType === "FIRST_PERIOD_PRICE") {
1109
+ const firstPeriodPrice = couponDiscountValue;
1110
+ const priceText = firstPeriodPrice === 0 ? "\u514D\u8CBB" : `\u7279\u50F9 ${formatPrice(firstPeriodPrice)}`;
1111
+ const line1 = bonusSuffix ? `\u9996\u671F${priceText}\uFF0C${bonusSuffix}` : `\u9996\u671F${priceText}`;
1112
+ return { line1, line2: afterLine };
1113
+ }
1114
+ if (discountType === "FIXED_AMOUNT") {
1115
+ return buildStandardDiscount({
1116
+ discountText: `\u6298 ${formatPrice(couponDiscountValue)}`,
1117
+ duration,
1118
+ durationMonths,
1119
+ bonusSuffix,
1120
+ afterLine
1121
+ });
1122
+ }
1123
+ if (discountType === "PERCENTAGE") {
1124
+ return buildStandardDiscount({
1125
+ discountText: `\u4EAB ${formatZhe(couponDiscountValue)}`,
1126
+ duration,
1127
+ durationMonths,
1128
+ bonusSuffix,
1129
+ afterLine
1130
+ });
1131
+ }
1132
+ return { line1: "", line2: null };
1133
+ }
1134
+ function buildStandardDiscount(opts) {
1135
+ const { discountText, duration, durationMonths, bonusSuffix, afterLine } = opts;
1136
+ switch (duration) {
1137
+ case "ONCE": {
1138
+ const base = `\u9996\u671F${discountText}`;
1139
+ const line1 = bonusSuffix ? `${base}\uFF0C${bonusSuffix}` : base;
1140
+ return { line1, line2: afterLine };
1141
+ }
1142
+ case "REPEATING": {
1143
+ const periods = durationMonths ?? 0;
1144
+ const line1 = `\u524D ${periods} \u671F\u6BCF\u671F${discountText}`;
1145
+ return { line1, line2: afterLine };
1146
+ }
1147
+ case "FOREVER": {
1148
+ const line1 = `\u6BCF\u671F${discountText}`;
1149
+ return { line1, line2: null };
1150
+ }
1151
+ default:
1152
+ return { line1: "", line2: null };
1153
+ }
1154
+ }
1155
+ function buildBonusSuffix(bonusMonths, bonusTrialDays) {
1156
+ const parts = [];
1157
+ if (bonusMonths) parts.push(`\u52A0\u9001 ${bonusMonths} \u500B\u6708`);
1158
+ if (bonusTrialDays) parts.push(`\u5EF6\u9577 ${bonusTrialDays} \u5929\u8A66\u7528`);
1159
+ if (parts.length === 0) return null;
1160
+ return `\u4E26${parts.join("\u53CA")}`;
1161
+ }
1162
+ function buildPureBonusLine(bonusMonths, bonusTrialDays) {
1163
+ const parts = [];
1164
+ if (bonusMonths) parts.push(`\u52A0\u9001 ${bonusMonths} \u500B\u6708`);
1165
+ if (bonusTrialDays) parts.push(`\u5EF6\u9577\u8A66\u7528 ${bonusTrialDays} \u5929`);
1166
+ return parts.join("\u53CA");
1167
+ }
1168
+ var init_checkout_display = __esm({
1169
+ "src/utils/checkout-display.ts"() {
1170
+ }
1171
+ });
1172
+
1055
1173
  // src/components/payment-form.ts
1056
1174
  var payment_form_exports = {};
1057
1175
  __export(payment_form_exports, {
@@ -1062,6 +1180,7 @@ var init_payment_form = __esm({
1062
1180
  "src/components/payment-form.ts"() {
1063
1181
  init_payment_form_shadow();
1064
1182
  init_payment_form_light();
1183
+ init_checkout_display();
1065
1184
  icons = {
1066
1185
  lock: litHtml.html`
1067
1186
  <svg class="security-icon" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -1365,73 +1484,26 @@ var init_payment_form = __esm({
1365
1484
  </div>
1366
1485
  `;
1367
1486
  }
1368
- // Helper to get interval text in Chinese
1369
- getIntervalText(interval, count) {
1370
- if (!interval) return "";
1371
- const countText = count && count > 1 ? count.toString() : "";
1372
- switch (interval.toUpperCase()) {
1373
- case "MONTH":
1374
- return `${countText}\u6708`;
1375
- case "YEAR":
1376
- return `${countText}\u5E74`;
1377
- case "WEEK":
1378
- return `${countText}\u9031`;
1379
- case "DAY":
1380
- return `${countText}\u5929`;
1381
- default:
1382
- return "";
1383
- }
1384
- }
1385
- // Get discount description based on type and duration
1386
- getDiscountDescription() {
1487
+ // Get unified discount display using shared function
1488
+ getDiscountDisplay() {
1387
1489
  if (!this._appliedCoupon) return null;
1388
- const { discountType, duration, durationMonths, productPrice, productInterval, productIntervalCount } = this._appliedCoupon;
1389
- const intervalText = this.getIntervalText(productInterval, productIntervalCount);
1390
- const originalPriceText = productPrice && intervalText ? `NT$ ${productPrice.toLocaleString()}/${intervalText}` : productPrice ? `NT$ ${productPrice.toLocaleString()}` : "";
1391
1490
  const amount = parseInt(this.getAttribute("amount") || "0", 10);
1392
- const finalAmount = amount - this._appliedCoupon.discountAmount;
1393
- if (discountType === "FIRST_PERIOD_PRICE") {
1394
- if (originalPriceText) {
1395
- return `\u9996\u671F\u53EA\u9700 NT$ ${finalAmount.toLocaleString()}\uFF0C\u4E4B\u5F8C ${originalPriceText}`;
1396
- }
1397
- return `\u9996\u671F\u53EA\u9700 NT$ ${finalAmount.toLocaleString()}`;
1398
- }
1399
- if (duration) {
1400
- switch (duration) {
1401
- case "ONCE":
1402
- if (originalPriceText) {
1403
- return `\u9996\u671F\u6298\u6263\uFF0C\u4E4B\u5F8C ${originalPriceText}`;
1404
- }
1405
- return "\u50C5\u9650\u9996\u671F";
1406
- case "REPEATING":
1407
- if (durationMonths) {
1408
- return `\u524D ${durationMonths} \u671F\u4EAB\u512A\u60E0\uFF0C\u4E4B\u5F8C\u6062\u5FA9\u539F\u50F9`;
1409
- }
1410
- return null;
1411
- case "FOREVER":
1412
- return "\u7D42\u8EAB\u512A\u60E0";
1413
- default:
1414
- return null;
1415
- }
1416
- }
1417
- return null;
1418
- }
1419
- // Get bonus description
1420
- getBonusDescription() {
1421
- if (!this._appliedCoupon) return null;
1422
- const parts = [];
1423
- if (this._appliedCoupon.bonusTrialDays) {
1424
- parts.push(`\u5EF6\u9577\u8A66\u7528 ${this._appliedCoupon.bonusTrialDays} \u5929`);
1425
- }
1426
- if (this._appliedCoupon.bonusMonths) {
1427
- parts.push(`\u52A0\u9001 ${this._appliedCoupon.bonusMonths} \u500B\u6708`);
1428
- }
1429
- return parts.length > 0 ? parts.join("\u3001") : null;
1491
+ return getCheckoutDiscountDisplay({
1492
+ discountType: this._appliedCoupon.discountType,
1493
+ couponDiscountValue: this._appliedCoupon.couponDiscountValue,
1494
+ discountAmount: this._appliedCoupon.discountAmount,
1495
+ duration: this._appliedCoupon.duration || "ONCE",
1496
+ durationMonths: this._appliedCoupon.durationMonths,
1497
+ productPrice: this._appliedCoupon.productPrice ?? amount,
1498
+ productInterval: this._appliedCoupon.productInterval,
1499
+ productIntervalCount: this._appliedCoupon.productIntervalCount,
1500
+ bonusMonths: this._appliedCoupon.bonusMonths,
1501
+ bonusTrialDays: this._appliedCoupon.bonusTrialDays
1502
+ });
1430
1503
  }
1431
1504
  renderCoupon() {
1432
1505
  if (this._appliedCoupon) {
1433
- const discountDescription = this.getDiscountDescription();
1434
- const bonusDescription = this.getBonusDescription();
1506
+ const display = this.getDiscountDisplay();
1435
1507
  return litHtml.html`
1436
1508
  <div class="recur-coupon__applied-wrapper">
1437
1509
  <div class="recur-coupon__applied">
@@ -1452,18 +1524,17 @@ var init_payment_form = __esm({
1452
1524
  ${this._couponLoading ? icons.spinner : icons.close}
1453
1525
  </button>
1454
1526
  </div>
1455
- <span class="recur-coupon__applied-amount">
1456
- -NT$ ${this._appliedCoupon.discountAmount.toLocaleString()}
1457
- </span>
1527
+ ${this._appliedCoupon.discountAmount > 0 ? litHtml.html`
1528
+ <span class="recur-coupon__applied-amount">
1529
+ -NT$ ${this._appliedCoupon.discountAmount.toLocaleString()}
1530
+ </span>
1531
+ ` : litHtml.nothing}
1458
1532
  </div>
1459
- ${discountDescription ? litHtml.html`
1460
- <p class="recur-coupon__description">${discountDescription}</p>
1533
+ ${display?.line1 ? litHtml.html`
1534
+ <p class="recur-coupon__description">${display.line1}</p>
1461
1535
  ` : litHtml.nothing}
1462
- ${bonusDescription ? litHtml.html`
1463
- <div class="recur-coupon__bonus">
1464
- <span>✨</span>
1465
- <span>${bonusDescription}</span>
1466
- </div>
1536
+ ${display?.line2 ? litHtml.html`
1537
+ <p class="recur-coupon__description">${display.line2}</p>
1467
1538
  ` : litHtml.nothing}
1468
1539
  </div>
1469
1540
  `;
@@ -1626,10 +1697,10 @@ var init_payment_form = __esm({
1626
1697
  getCouponAppliedHTML() {
1627
1698
  const coupon = this._appliedCoupon;
1628
1699
  const nameHTML = coupon.couponName ? `<span class="recur-coupon__applied-name">${coupon.couponName}</span><span class="recur-coupon__applied-code">(${coupon.code})</span>` : `<span class="recur-coupon__applied-name">${coupon.code}</span>`;
1629
- const discountDescription = this.getDiscountDescription();
1630
- const bonusDescription = this.getBonusDescription();
1631
- const descriptionHTML = discountDescription ? `<p class="recur-coupon__description">${discountDescription}</p>` : "";
1632
- const bonusHTML = bonusDescription ? `<div class="recur-coupon__bonus"><span>\u2728</span><span>${bonusDescription}</span></div>` : "";
1700
+ const display = this.getDiscountDisplay();
1701
+ const amountHTML = coupon.discountAmount > 0 ? `<span class="recur-coupon__applied-amount">-NT$ ${coupon.discountAmount.toLocaleString()}</span>` : "";
1702
+ const line1HTML = display?.line1 ? `<p class="recur-coupon__description">${display.line1}</p>` : "";
1703
+ const line2HTML = display?.line2 ? `<p class="recur-coupon__description">${display.line2}</p>` : "";
1633
1704
  return `
1634
1705
  <div class="recur-coupon__applied-wrapper">
1635
1706
  <div class="recur-coupon__applied">
@@ -1642,10 +1713,10 @@ var init_payment_form = __esm({
1642
1713
  ${this._couponLoading ? '<span class="recur-coupon__spinner"></span>' : '<svg class="recur-coupon__remove-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /></svg>'}
1643
1714
  </button>
1644
1715
  </div>
1645
- <span class="recur-coupon__applied-amount">-NT$ ${coupon.discountAmount.toLocaleString()}</span>
1716
+ ${amountHTML}
1646
1717
  </div>
1647
- ${descriptionHTML}
1648
- ${bonusHTML}
1718
+ ${line1HTML}
1719
+ ${line2HTML}
1649
1720
  </div>
1650
1721
  `;
1651
1722
  }
@@ -1717,6 +1788,7 @@ var init_payment_form = __esm({
1717
1788
  couponName: data.discount.coupon_name,
1718
1789
  discountType: data.discount.discount_type,
1719
1790
  discountAmount: data.discount.discount_amount,
1791
+ couponDiscountValue: data.discount.coupon_discount_value ?? data.discount.discount_amount,
1720
1792
  duration: data.discount.duration,
1721
1793
  durationMonths: data.discount.duration_months,
1722
1794
  bonusTrialDays: data.discount.bonus_trial_days,
@@ -2742,7 +2814,7 @@ function toCamelCase(obj) {
2742
2814
 
2743
2815
  // package.json
2744
2816
  var package_default = {
2745
- version: "0.13.0"};
2817
+ version: "0.13.2"};
2746
2818
  var SDK_VERSION = package_default.version;
2747
2819
  var SDK_TYPE = "react";
2748
2820
  var RecurContext = React.createContext(null);
@@ -2961,6 +3033,8 @@ function RecurProvider({ children, config: initialConfig = {}, customer: custome
2961
3033
  dialog.className = "recur-sdk__dialog";
2962
3034
  dialogContent = document.createElement("div");
2963
3035
  dialogContent.className = "recur-sdk__dialog-content";
3036
+ dialogContent.setAttribute("tabindex", "-1");
3037
+ dialogContent.setAttribute("autofocus", "");
2964
3038
  dialogContent.style.cssText = `
2965
3039
  max-width: 500px;
2966
3040
  width: 100%;
@@ -2971,6 +3045,7 @@ function RecurProvider({ children, config: initialConfig = {}, customer: custome
2971
3045
  border-radius: 12px;
2972
3046
  background: white;
2973
3047
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);
3048
+ outline: none;
2974
3049
  `;
2975
3050
  const closeButton = document.createElement("button");
2976
3051
  closeButton.className = "recur-sdk__close-button";
package/dist/index.d.cts CHANGED
@@ -929,9 +929,7 @@ declare class RecurPaymentForm extends HTMLElement {
929
929
  private isTestMode;
930
930
  private renderTestCardHints;
931
931
  private renderOrderSummary;
932
- private getIntervalText;
933
- private getDiscountDescription;
934
- private getBonusDescription;
932
+ private getDiscountDisplay;
935
933
  private renderCoupon;
936
934
  private showCouponInput;
937
935
  private cancelCouponInput;
@@ -957,6 +955,7 @@ declare class RecurPaymentForm extends HTMLElement {
957
955
  couponName: string;
958
956
  discountType: string;
959
957
  discountAmount: number;
958
+ couponDiscountValue: number;
960
959
  duration?: string;
961
960
  durationMonths?: number;
962
961
  bonusTrialDays?: number;
package/dist/index.d.ts CHANGED
@@ -929,9 +929,7 @@ declare class RecurPaymentForm extends HTMLElement {
929
929
  private isTestMode;
930
930
  private renderTestCardHints;
931
931
  private renderOrderSummary;
932
- private getIntervalText;
933
- private getDiscountDescription;
934
- private getBonusDescription;
932
+ private getDiscountDisplay;
935
933
  private renderCoupon;
936
934
  private showCouponInput;
937
935
  private cancelCouponInput;
@@ -957,6 +955,7 @@ declare class RecurPaymentForm extends HTMLElement {
957
955
  couponName: string;
958
956
  discountType: string;
959
957
  discountAmount: number;
958
+ couponDiscountValue: number;
960
959
  duration?: string;
961
960
  durationMonths?: number;
962
961
  bonusTrialDays?: number;