recur-tw 0.9.10 → 0.9.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -657,11 +657,11 @@ var init_payment_form_skeleton2 = __esm({
657
657
  <h3 class="section-title">訂單摘要</h3>
658
658
  <div class="order-summary">
659
659
  <div class="order-row">
660
- <span class="order-label">訂閱方案</span>
661
- <div class="skeleton skeleton-order-value"></div>
660
+ <span class="order-label">方案</span>
661
+ <div class="skeleton skeleton-order-value" style="width: 120px;"></div>
662
662
  </div>
663
663
  <div class="order-row">
664
- <span class="order-label">計費週期</span>
664
+ <span class="order-label">小計</span>
665
665
  <div class="skeleton skeleton-order-value"></div>
666
666
  </div>
667
667
  <div class="coupon-section">
@@ -1035,7 +1035,7 @@ var init_payment_form_shadow = __esm({
1035
1035
  var payment_form_light_default;
1036
1036
  var init_payment_form_light = __esm({
1037
1037
  "src/components/styles/payment-form-light.css"() {
1038
- payment_form_light_default = "/**\n * Payment Form - Light DOM Styles\n * These styles are applied to slotted content in the Light DOM\n * Using BEM naming convention with 'recur-' prefix for isolation\n */\n\n/* ============================================\n * Order Summary Styles\n * ============================================ */\n.recur-order-summary {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n}\n\n.recur-order-summary__row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.recur-order-summary__row--total {\n margin-bottom: 0;\n padding-top: 12px;\n border-top: 1px solid #e2e8f0;\n}\n\n.recur-order-summary__label {\n font-size: 14px;\n color: #4a5568;\n}\n\n.recur-order-summary__value {\n font-size: 14px;\n line-height: 20px;\n font-weight: 500;\n color: #2d3748;\n}\n\n.recur-order-summary__total {\n font-size: 18px;\n line-height: 26px;\n font-weight: 700;\n color: #1a202c;\n}\n\n/* ============================================\n * Coupon Section Styles\n * ============================================ */\n.recur-coupon {\n padding: 12px 0;\n border-top: 1px solid #e2e8f0;\n margin-top: 12px;\n min-height: 36px;\n display: flex;\n align-items: center;\n}\n\n.recur-coupon__trigger {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n height: 36px;\n background: none;\n border: none;\n padding: 0;\n font-size: 14px;\n line-height: 1;\n color: #718096;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.recur-coupon__trigger:hover {\n color: #4a5568;\n}\n\n.recur-coupon__trigger-icon {\n width: 16px;\n height: 16px;\n}\n\n.recur-coupon__input-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 36px;\n}\n\n.recur-coupon__input {\n flex: 1;\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n text-transform: uppercase;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n outline: none;\n transition: border-color 0.2s, box-shadow 0.2s;\n}\n\n.recur-coupon__input::placeholder {\n text-transform: none;\n}\n\n.recur-coupon__input:focus {\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.recur-coupon__btn {\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s, opacity 0.2s;\n white-space: nowrap;\n}\n\n.recur-coupon__btn--apply {\n background: #18181b;\n color: white;\n border: none;\n}\n\n.recur-coupon__btn--apply:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-coupon__btn--apply:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.recur-coupon__btn--cancel {\n background: transparent;\n color: #718096;\n border: 1px solid #d1d5db;\n}\n\n.recur-coupon__btn--cancel:hover {\n background: #f7fafc;\n}\n\n.recur-coupon__error {\n width: 100%;\n margin-top: 8px;\n font-size: 13px;\n color: #dc2626;\n}\n\n.recur-coupon__applied {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n}\n\n.recur-coupon__applied-info {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n min-width: 0;\n}\n\n.recur-coupon__applied-icon {\n width: 16px;\n height: 16px;\n color: #16a34a;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.recur-coupon__applied-details {\n min-width: 0;\n}\n\n.recur-coupon__applied-name {\n font-size: 14px;\n font-weight: 500;\n color: #16a34a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.recur-coupon__applied-code {\n font-size: 12px;\n color: #718096;\n}\n\n.recur-coupon__applied-amount {\n font-size: 14px;\n font-weight: 500;\n color: #16a34a;\n white-space: nowrap;\n}\n\n.recur-coupon__remove {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #9ca3af;\n border-radius: 4px;\n transition: color 0.2s, background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.recur-coupon__remove:hover {\n color: #6b7280;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.recur-coupon__remove-icon {\n width: 14px;\n height: 14px;\n}\n\n.recur-coupon__spinner {\n width: 14px;\n height: 14px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n/* Discount Row */\n.recur-order-summary__row--discount {\n color: #16a34a;\n}\n\n.recur-order-summary__row--discount .recur-order-summary__value {\n color: #16a34a;\n font-weight: 500;\n}\n\n/* ============================================\n * Customer Info Styles\n * ============================================ */\n.recur-info-display {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 8px;\n}\n\n.recur-info-row {\n margin-bottom: 12px;\n}\n\n.recur-info-row:last-child {\n margin-bottom: 0;\n}\n\n.recur-info-label {\n display: block;\n font-size: 12px;\n line-height: 16px;\n color: #718096;\n margin-bottom: 2px;\n}\n\n.recur-info-value {\n display: block;\n font-size: 14px;\n line-height: 20px;\n min-height: 20px;\n color: #2d3748;\n font-weight: 500;\n word-break: break-all;\n}\n\n.recur-form-group {\n margin-bottom: 16px;\n}\n\n.recur-form-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-form-input {\n width: 100%;\n padding: 10px 12px;\n font-size: 16px;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n transition: border-color 0.2s;\n box-sizing: border-box;\n}\n\n.recur-form-input:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.recur-form-input:hover:not(:focus) {\n border-color: #9ca3af;\n}\n\n/* ============================================\n * Card Fields Styles\n * ============================================ */\n.recur-card-field {\n margin-bottom: 16px;\n}\n\n.recur-card-field-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-payuni-iframe {\n height: 36px;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n touch-action: manipulation;\n}\n\n.recur-card-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n column-gap: 16px;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n.recur-card-field-container {\n position: relative;\n touch-action: manipulation;\n}\n\n.recur-card-skeleton {\n position: absolute;\n top: 0;\n left: 0;\n height: 36px;\n width: 100%;\n background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);\n background-size: 200% 100%;\n animation: recur-skeleton-loading 1.5s ease-in-out infinite;\n border-radius: 4px;\n z-index: 1;\n pointer-events: none;\n}\n\n.recur-card-skeleton.hidden {\n display: none;\n}\n\n@keyframes recur-skeleton-loading {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n/* ============================================\n * Submit Button Styles\n * ============================================ */\n.recur-submit-button {\n width: 100%;\n padding: 14px 20px;\n font-size: 16px;\n font-weight: 500;\n color: #ffffff;\n background: #18181b;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n box-sizing: border-box;\n}\n\n.recur-submit-button:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-submit-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.recur-submit-button.loading {\n cursor: wait;\n}\n\n.recur-loading-spinner {\n width: 16px;\n height: 16px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n@keyframes recur-spin {\n to { transform: rotate(360deg); }\n}\n";
1038
+ payment_form_light_default = "/**\n * Payment Form - Light DOM Styles\n * These styles are applied to slotted content in the Light DOM\n * Using BEM naming convention with 'recur-' prefix for isolation\n */\n\n/* ============================================\n * Order Summary Styles\n * ============================================ */\n.recur-order-summary {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n}\n\n.recur-order-summary__row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.recur-order-summary__row--total {\n margin-bottom: 0;\n padding-top: 12px;\n border-top: 1px solid #e2e8f0;\n}\n\n.recur-order-summary__label {\n font-size: 14px;\n color: #4a5568;\n}\n\n.recur-order-summary__value {\n font-size: 14px;\n line-height: 20px;\n font-weight: 500;\n color: #2d3748;\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n.recur-order-summary__total {\n font-size: 18px;\n line-height: 26px;\n font-weight: 700;\n color: #1a202c;\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n/* ============================================\n * Coupon Section Styles\n * ============================================ */\n.recur-coupon {\n padding: 12px 0;\n border-top: 1px solid #e2e8f0;\n margin-top: 12px;\n min-height: 36px;\n display: flex;\n align-items: center;\n}\n\n.recur-coupon__trigger {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n height: 36px;\n background: none;\n border: none;\n padding: 0;\n font-size: 14px;\n line-height: 1;\n color: #718096;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.recur-coupon__trigger:hover {\n color: #4a5568;\n}\n\n.recur-coupon__trigger-icon {\n width: 16px;\n height: 16px;\n}\n\n.recur-coupon__input-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 36px;\n}\n\n.recur-coupon__input {\n flex: 1;\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n text-transform: uppercase;\n background-color: #ffffff;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n outline: none;\n transition: border-color 0.2s, box-shadow 0.2s;\n}\n\n.recur-coupon__input::placeholder {\n text-transform: none;\n}\n\n.recur-coupon__input:hover:not(:focus) {\n border-color: #9ca3af;\n}\n\n.recur-coupon__input:focus {\n border-color: var(--ring, hsl(215 16% 47%));\n outline: 0;\n box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring, hsl(215 16% 47%)) 50%, transparent);\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n.recur-coupon__btn {\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s, opacity 0.2s;\n white-space: nowrap;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.recur-coupon__btn--apply {\n background: #18181b;\n color: white;\n border: none;\n min-width: 52px;\n}\n\n.recur-coupon__btn--apply .recur-coupon__spinner {\n width: 14px;\n height: 14px;\n}\n\n.recur-coupon__btn--apply:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-coupon__btn--apply:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.recur-coupon__btn--cancel {\n background: transparent;\n color: #718096;\n border: 1px solid #d1d5db;\n}\n\n.recur-coupon__btn--cancel:hover {\n background: #f7fafc;\n}\n\n.recur-coupon__error {\n width: 100%;\n margin-top: 8px;\n font-size: 13px;\n color: #dc2626;\n}\n\n.recur-coupon__applied {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 36px;\n}\n\n.recur-coupon__applied-info {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n flex: 1;\n}\n\n.recur-coupon__applied-icon {\n width: 16px;\n height: 16px;\n color: #dc2626;\n flex-shrink: 0;\n}\n\n.recur-coupon__applied-name {\n font-size: 14px;\n font-weight: 500;\n color: #dc2626;\n white-space: nowrap;\n}\n\n.recur-coupon__applied-code {\n font-size: 14px;\n color: #9ca3af;\n white-space: nowrap;\n margin-right: 2px;\n}\n\n.recur-coupon__applied-amount {\n font-size: 14px;\n font-weight: 500;\n color: #dc2626;\n white-space: nowrap;\n font-variant-numeric: tabular-nums;\n flex-shrink: 0;\n margin-left: auto;\n}\n\n.recur-coupon__remove {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #9ca3af;\n border-radius: 4px;\n transition: color 0.2s, background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.recur-coupon__remove:hover {\n color: #6b7280;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.recur-coupon__remove-icon {\n width: 14px;\n height: 14px;\n}\n\n.recur-coupon__spinner {\n width: 14px;\n height: 14px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n/* Discount Row */\n.recur-order-summary__row--discount {\n color: #16a34a;\n}\n\n.recur-order-summary__row--discount .recur-order-summary__value {\n color: #16a34a;\n font-weight: 500;\n}\n\n/* ============================================\n * Customer Info Styles\n * ============================================ */\n.recur-info-display {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 8px;\n}\n\n.recur-info-row {\n margin-bottom: 12px;\n}\n\n.recur-info-row:last-child {\n margin-bottom: 0;\n}\n\n.recur-info-label {\n display: block;\n font-size: 12px;\n line-height: 16px;\n color: #718096;\n margin-bottom: 2px;\n}\n\n.recur-info-value {\n display: block;\n font-size: 14px;\n line-height: 20px;\n min-height: 20px;\n color: #2d3748;\n font-weight: 500;\n word-break: break-all;\n}\n\n.recur-form-group {\n margin-bottom: 16px;\n}\n\n.recur-form-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-form-input {\n width: 100%;\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n transition: border-color 0.2s;\n box-sizing: border-box;\n}\n\n.recur-form-input:focus {\n border-color: var(--ring, hsl(215 16% 47%));\n outline: 0;\n box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring, hsl(215 16% 47%)) 50%, transparent);\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n.recur-form-input:hover:not(:focus) {\n border-color: #9ca3af;\n}\n\n/* ============================================\n * Card Fields Styles\n * ============================================ */\n.recur-card-field {\n margin-bottom: 16px;\n}\n\n.recur-card-field-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-payuni-iframe {\n height: 36px;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n touch-action: manipulation;\n}\n\n.recur-card-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n column-gap: 16px;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n.recur-card-field-container {\n position: relative;\n touch-action: manipulation;\n}\n\n.recur-card-skeleton {\n position: absolute;\n top: 0;\n left: 0;\n height: 36px;\n width: 100%;\n background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);\n background-size: 200% 100%;\n animation: recur-skeleton-loading 1.5s ease-in-out infinite;\n border-radius: 4px;\n z-index: 1;\n pointer-events: none;\n}\n\n.recur-card-skeleton.hidden {\n display: none;\n}\n\n@keyframes recur-skeleton-loading {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n/* ============================================\n * Submit Button Styles\n * ============================================ */\n.recur-submit-button {\n width: 100%;\n padding: 14px 20px;\n font-size: 16px;\n font-weight: 500;\n color: #ffffff;\n background: #18181b;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n box-sizing: border-box;\n}\n\n.recur-submit-button:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-submit-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.recur-submit-button.loading {\n cursor: wait;\n}\n\n.recur-loading-spinner {\n width: 16px;\n height: 16px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n@keyframes recur-spin {\n to { transform: rotate(360deg); }\n}\n\n/* ============================================\n * Skeleton Loading Styles\n * ============================================ */\n.recur-skeleton {\n display: inline-block;\n background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);\n background-size: 200% 100%;\n animation: recur-skeleton-loading 1.5s ease-in-out infinite;\n border-radius: 4px;\n}\n";
1039
1039
  }
1040
1040
  });
1041
1041
 
@@ -1224,7 +1224,25 @@ var init_payment_form = __esm({
1224
1224
  const amount = this.getAttribute("amount");
1225
1225
  const interval = this.getAttribute("interval");
1226
1226
  if (!productName || !amount) {
1227
- return litHtml.html`<div class="recur-order-summary" style="display: none;"></div>`;
1227
+ return litHtml.html`
1228
+ <div class="recur-order-summary" id="${this.containerId}-order-summary">
1229
+ <div class="recur-order-summary__row">
1230
+ <span class="recur-order-summary__label">方案</span>
1231
+ <span class="recur-order-summary__value recur-skeleton" style="width: 120px; height: 20px;"></span>
1232
+ </div>
1233
+ <div class="recur-order-summary__row">
1234
+ <span class="recur-order-summary__label">小計</span>
1235
+ <span class="recur-order-summary__value recur-skeleton" style="width: 80px; height: 20px;"></span>
1236
+ </div>
1237
+ <div class="recur-coupon">
1238
+ <span class="recur-skeleton" style="width: 80px; height: 20px;"></span>
1239
+ </div>
1240
+ <div class="recur-order-summary__row recur-order-summary__row--total">
1241
+ <span class="recur-order-summary__label">總計</span>
1242
+ <span class="recur-order-summary__total recur-skeleton" style="width: 100px; height: 26px;"></span>
1243
+ </div>
1244
+ </div>
1245
+ `;
1228
1246
  }
1229
1247
  const intervalMap = {
1230
1248
  "day": "\u65E5",
@@ -1236,35 +1254,26 @@ var init_payment_form = __esm({
1236
1254
  const originalAmount = Number(amount);
1237
1255
  const discountAmount = this._appliedCoupon?.discountAmount || 0;
1238
1256
  const finalAmount = originalAmount - discountAmount;
1257
+ const productDisplay = periodText ? `${productName} / \u6BCF${periodText}` : productName;
1239
1258
  return litHtml.html`
1240
1259
  <div class="recur-order-summary" id="${this.containerId}-order-summary">
1241
1260
  <div class="recur-order-summary__row">
1242
- <span class="recur-order-summary__label">訂閱方案</span>
1243
- <span class="recur-order-summary__value">${productName}</span>
1261
+ <span class="recur-order-summary__label">方案</span>
1262
+ <span class="recur-order-summary__value">${productDisplay}</span>
1244
1263
  </div>
1245
1264
 
1246
- ${periodText ? litHtml.html`
1247
- <div class="recur-order-summary__row">
1248
- <span class="recur-order-summary__label">計費週期</span>
1249
- <span class="recur-order-summary__value">每${periodText}</span>
1250
- </div>
1251
- ` : litHtml.nothing}
1265
+ <!-- 小計 (Subtotal) - always show -->
1266
+ <div class="recur-order-summary__row">
1267
+ <span class="recur-order-summary__label">小計</span>
1268
+ <span class="recur-order-summary__value">NT$ ${originalAmount.toLocaleString()}</span>
1269
+ </div>
1252
1270
 
1271
+ <!-- 優惠碼區塊 (Coupon section with discount amount) -->
1253
1272
  <div class="recur-coupon" id="${this.containerId}-coupon">
1254
1273
  ${this.renderCoupon()}
1255
1274
  </div>
1256
1275
 
1257
- ${discountAmount > 0 ? litHtml.html`
1258
- <div class="recur-order-summary__row">
1259
- <span class="recur-order-summary__label">小計</span>
1260
- <span class="recur-order-summary__value">NT$ ${originalAmount.toLocaleString()}</span>
1261
- </div>
1262
- <div class="recur-order-summary__row recur-order-summary__row--discount">
1263
- <span class="recur-order-summary__label">折扣</span>
1264
- <span class="recur-order-summary__value">-NT$ ${discountAmount.toLocaleString()}</span>
1265
- </div>
1266
- ` : litHtml.nothing}
1267
-
1276
+ <!-- 總計 (Total) -->
1268
1277
  <div class="recur-order-summary__row recur-order-summary__row--total">
1269
1278
  <span class="recur-order-summary__label">總計</span>
1270
1279
  <span class="recur-order-summary__total">NT$ ${finalAmount.toLocaleString()}</span>
@@ -1278,26 +1287,24 @@ var init_payment_form = __esm({
1278
1287
  <div class="recur-coupon__applied">
1279
1288
  <div class="recur-coupon__applied-info">
1280
1289
  ${icons.tagApplied}
1281
- <div class="recur-coupon__applied-details">
1282
- <div class="recur-coupon__applied-name">
1283
- ${this._appliedCoupon.couponName || this._appliedCoupon.code}
1284
- </div>
1285
- ${this._appliedCoupon.couponName ? litHtml.html`
1286
- <div class="recur-coupon__applied-code">代碼:${this._appliedCoupon.code}</div>
1287
- ` : litHtml.nothing}
1288
- </div>
1290
+ ${this._appliedCoupon.couponName ? litHtml.html`
1291
+ <span class="recur-coupon__applied-name">${this._appliedCoupon.couponName}</span>
1292
+ <span class="recur-coupon__applied-code">(${this._appliedCoupon.code})</span>
1293
+ ` : litHtml.html`
1294
+ <span class="recur-coupon__applied-name">${this._appliedCoupon.code}</span>
1295
+ `}
1296
+ <button
1297
+ type="button"
1298
+ class="recur-coupon__remove"
1299
+ ?disabled=${this._couponLoading}
1300
+ @click=${() => this.removeCoupon()}
1301
+ >
1302
+ ${this._couponLoading ? icons.spinner : icons.close}
1303
+ </button>
1289
1304
  </div>
1290
1305
  <span class="recur-coupon__applied-amount">
1291
1306
  -NT$ ${this._appliedCoupon.discountAmount.toLocaleString()}
1292
1307
  </span>
1293
- <button
1294
- type="button"
1295
- class="recur-coupon__remove"
1296
- ?disabled=${this._couponLoading}
1297
- @click=${() => this.removeCoupon()}
1298
- >
1299
- ${this._couponLoading ? icons.spinner : icons.close}
1300
- </button>
1301
1308
  </div>
1302
1309
  `;
1303
1310
  }
@@ -1386,7 +1393,8 @@ var init_payment_form = __esm({
1386
1393
  }
1387
1394
  // Direct DOM manipulation for coupon section updates (avoids lit-html tracking issues)
1388
1395
  updateCouponSectionDOM() {
1389
- const container = document.getElementById(`${this.containerId}-coupon`);
1396
+ const containerId = `${this.containerId}-coupon`;
1397
+ const container = document.getElementById(containerId);
1390
1398
  if (!container) return;
1391
1399
  if (this._appliedCoupon) {
1392
1400
  container.innerHTML = this.getCouponAppliedHTML();
@@ -1443,22 +1451,19 @@ var init_payment_form = __esm({
1443
1451
  }
1444
1452
  getCouponAppliedHTML() {
1445
1453
  const coupon = this._appliedCoupon;
1446
- const codeHTML = coupon.couponName ? `<div class="recur-coupon__applied-code">\u4EE3\u78BC\uFF1A${coupon.code}</div>` : "";
1454
+ 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>`;
1447
1455
  return `
1448
1456
  <div class="recur-coupon__applied">
1449
1457
  <div class="recur-coupon__applied-info">
1450
1458
  <svg class="recur-coupon__applied-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1451
1459
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
1452
1460
  </svg>
1453
- <div class="recur-coupon__applied-details">
1454
- <div class="recur-coupon__applied-name">${coupon.couponName || coupon.code}</div>
1455
- ${codeHTML}
1456
- </div>
1461
+ ${nameHTML}
1462
+ <button type="button" class="recur-coupon__remove" ${this._couponLoading ? "disabled" : ""}>
1463
+ ${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>'}
1464
+ </button>
1457
1465
  </div>
1458
1466
  <span class="recur-coupon__applied-amount">-NT$ ${coupon.discountAmount.toLocaleString()}</span>
1459
- <button type="button" class="recur-coupon__remove" ${this._couponLoading ? "disabled" : ""}>
1460
- ${this._couponLoading ? '<span class="recur-coupon__spinner"></span>' : '<svg class="recur-coupon__remove-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /></svg>'}
1461
- </button>
1462
1467
  </div>
1463
1468
  `;
1464
1469
  }
@@ -1485,31 +1490,7 @@ var init_payment_form = __esm({
1485
1490
  const amount = Number(this.getAttribute("amount") || 0);
1486
1491
  const discountAmount = this._appliedCoupon?.discountAmount || 0;
1487
1492
  const finalAmount = amount - discountAmount;
1488
- let discountRow = summaryContainer.querySelector(".recur-order-summary__row--discount");
1489
1493
  const totalRow = summaryContainer.querySelector(".recur-order-summary__row--total");
1490
- if (discountAmount > 0) {
1491
- if (!discountRow && totalRow) {
1492
- const subtotalHTML = `
1493
- <div class="recur-order-summary__row">
1494
- <span class="recur-order-summary__label">\u5C0F\u8A08</span>
1495
- <span class="recur-order-summary__value">NT$ ${amount.toLocaleString()}</span>
1496
- </div>
1497
- `;
1498
- const discountHTML = `
1499
- <div class="recur-order-summary__row recur-order-summary__row--discount">
1500
- <span class="recur-order-summary__label">\u6298\u6263</span>
1501
- <span class="recur-order-summary__value">-NT$ ${discountAmount.toLocaleString()}</span>
1502
- </div>
1503
- `;
1504
- totalRow.insertAdjacentHTML("beforebegin", subtotalHTML + discountHTML);
1505
- }
1506
- } else {
1507
- const subtotalRow = summaryContainer.querySelector(".recur-order-summary__row:not(.recur-order-summary__row--total):last-of-type");
1508
- discountRow?.remove();
1509
- if (subtotalRow?.querySelector(".recur-order-summary__label")?.textContent === "\u5C0F\u8A08") {
1510
- subtotalRow.remove();
1511
- }
1512
- }
1513
1494
  const totalValue = totalRow?.querySelector(".recur-order-summary__total");
1514
1495
  if (totalValue) {
1515
1496
  totalValue.textContent = `NT$ ${finalAmount.toLocaleString()}`;
@@ -1537,7 +1518,7 @@ var init_payment_form = __esm({
1537
1518
  this._couponError = null;
1538
1519
  this.updateCouponSectionDOM();
1539
1520
  try {
1540
- const response = await fetch(`${apiBaseUrl}/api/checkout/${checkoutId}/coupon`, {
1521
+ const response = await fetch(`${apiBaseUrl}/v1/checkouts/${checkoutId}/coupon`, {
1541
1522
  method: "POST",
1542
1523
  headers: { "Content-Type": "application/json" },
1543
1524
  body: JSON.stringify({ code })
@@ -1583,7 +1564,7 @@ var init_payment_form = __esm({
1583
1564
  this._couponLoading = true;
1584
1565
  this.updateCouponSectionDOM();
1585
1566
  try {
1586
- const response = await fetch(`${apiBaseUrl}/api/checkout/${checkoutId}/coupon`, {
1567
+ const response = await fetch(`${apiBaseUrl}/v1/checkouts/${checkoutId}/coupon`, {
1587
1568
  method: "DELETE"
1588
1569
  });
1589
1570
  if (!response.ok) {
@@ -2565,7 +2546,7 @@ function toCamelCase(obj) {
2565
2546
 
2566
2547
  // package.json
2567
2548
  var package_default = {
2568
- version: "0.9.9"};
2549
+ version: "0.9.12"};
2569
2550
  var SDK_VERSION = package_default.version;
2570
2551
  var SDK_TYPE = "react";
2571
2552
  var RecurContext = React.createContext(null);
@@ -2881,6 +2862,10 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2881
2862
  container.innerHTML = "";
2882
2863
  const paymentForm = document.createElement("recur-payment-form");
2883
2864
  paymentForm.setAttribute("container-id", containerElementId);
2865
+ if (checkoutResult.checkout?.id) {
2866
+ paymentForm.setAttribute("checkout-id", checkoutResult.checkout.id);
2867
+ }
2868
+ paymentForm.setAttribute("api-base-url", baseUrl);
2884
2869
  if (options.customerName) {
2885
2870
  paymentForm.setAttribute("customer-name", options.customerName);
2886
2871
  }
@@ -2897,7 +2882,6 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2897
2882
  paymentForm.setAttribute("interval", checkoutResult.product.interval);
2898
2883
  }
2899
2884
  const customStyles = `
2900
- /* PAYUNi SDK focus \u6A23\u5F0F - shadcn \u98A8\u683C */
2901
2885
  .form-input-focus {
2902
2886
  border-color: var(--ring, hsl(215 16% 47%)) !important;
2903
2887
  outline: 0 !important;
package/dist/index.js CHANGED
@@ -651,11 +651,11 @@ var init_payment_form_skeleton2 = __esm({
651
651
  <h3 class="section-title">訂單摘要</h3>
652
652
  <div class="order-summary">
653
653
  <div class="order-row">
654
- <span class="order-label">訂閱方案</span>
655
- <div class="skeleton skeleton-order-value"></div>
654
+ <span class="order-label">方案</span>
655
+ <div class="skeleton skeleton-order-value" style="width: 120px;"></div>
656
656
  </div>
657
657
  <div class="order-row">
658
- <span class="order-label">計費週期</span>
658
+ <span class="order-label">小計</span>
659
659
  <div class="skeleton skeleton-order-value"></div>
660
660
  </div>
661
661
  <div class="coupon-section">
@@ -1029,7 +1029,7 @@ var init_payment_form_shadow = __esm({
1029
1029
  var payment_form_light_default;
1030
1030
  var init_payment_form_light = __esm({
1031
1031
  "src/components/styles/payment-form-light.css"() {
1032
- payment_form_light_default = "/**\n * Payment Form - Light DOM Styles\n * These styles are applied to slotted content in the Light DOM\n * Using BEM naming convention with 'recur-' prefix for isolation\n */\n\n/* ============================================\n * Order Summary Styles\n * ============================================ */\n.recur-order-summary {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n}\n\n.recur-order-summary__row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.recur-order-summary__row--total {\n margin-bottom: 0;\n padding-top: 12px;\n border-top: 1px solid #e2e8f0;\n}\n\n.recur-order-summary__label {\n font-size: 14px;\n color: #4a5568;\n}\n\n.recur-order-summary__value {\n font-size: 14px;\n line-height: 20px;\n font-weight: 500;\n color: #2d3748;\n}\n\n.recur-order-summary__total {\n font-size: 18px;\n line-height: 26px;\n font-weight: 700;\n color: #1a202c;\n}\n\n/* ============================================\n * Coupon Section Styles\n * ============================================ */\n.recur-coupon {\n padding: 12px 0;\n border-top: 1px solid #e2e8f0;\n margin-top: 12px;\n min-height: 36px;\n display: flex;\n align-items: center;\n}\n\n.recur-coupon__trigger {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n height: 36px;\n background: none;\n border: none;\n padding: 0;\n font-size: 14px;\n line-height: 1;\n color: #718096;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.recur-coupon__trigger:hover {\n color: #4a5568;\n}\n\n.recur-coupon__trigger-icon {\n width: 16px;\n height: 16px;\n}\n\n.recur-coupon__input-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 36px;\n}\n\n.recur-coupon__input {\n flex: 1;\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n text-transform: uppercase;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n outline: none;\n transition: border-color 0.2s, box-shadow 0.2s;\n}\n\n.recur-coupon__input::placeholder {\n text-transform: none;\n}\n\n.recur-coupon__input:focus {\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.recur-coupon__btn {\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s, opacity 0.2s;\n white-space: nowrap;\n}\n\n.recur-coupon__btn--apply {\n background: #18181b;\n color: white;\n border: none;\n}\n\n.recur-coupon__btn--apply:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-coupon__btn--apply:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.recur-coupon__btn--cancel {\n background: transparent;\n color: #718096;\n border: 1px solid #d1d5db;\n}\n\n.recur-coupon__btn--cancel:hover {\n background: #f7fafc;\n}\n\n.recur-coupon__error {\n width: 100%;\n margin-top: 8px;\n font-size: 13px;\n color: #dc2626;\n}\n\n.recur-coupon__applied {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n}\n\n.recur-coupon__applied-info {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n min-width: 0;\n}\n\n.recur-coupon__applied-icon {\n width: 16px;\n height: 16px;\n color: #16a34a;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.recur-coupon__applied-details {\n min-width: 0;\n}\n\n.recur-coupon__applied-name {\n font-size: 14px;\n font-weight: 500;\n color: #16a34a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.recur-coupon__applied-code {\n font-size: 12px;\n color: #718096;\n}\n\n.recur-coupon__applied-amount {\n font-size: 14px;\n font-weight: 500;\n color: #16a34a;\n white-space: nowrap;\n}\n\n.recur-coupon__remove {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #9ca3af;\n border-radius: 4px;\n transition: color 0.2s, background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.recur-coupon__remove:hover {\n color: #6b7280;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.recur-coupon__remove-icon {\n width: 14px;\n height: 14px;\n}\n\n.recur-coupon__spinner {\n width: 14px;\n height: 14px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n/* Discount Row */\n.recur-order-summary__row--discount {\n color: #16a34a;\n}\n\n.recur-order-summary__row--discount .recur-order-summary__value {\n color: #16a34a;\n font-weight: 500;\n}\n\n/* ============================================\n * Customer Info Styles\n * ============================================ */\n.recur-info-display {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 8px;\n}\n\n.recur-info-row {\n margin-bottom: 12px;\n}\n\n.recur-info-row:last-child {\n margin-bottom: 0;\n}\n\n.recur-info-label {\n display: block;\n font-size: 12px;\n line-height: 16px;\n color: #718096;\n margin-bottom: 2px;\n}\n\n.recur-info-value {\n display: block;\n font-size: 14px;\n line-height: 20px;\n min-height: 20px;\n color: #2d3748;\n font-weight: 500;\n word-break: break-all;\n}\n\n.recur-form-group {\n margin-bottom: 16px;\n}\n\n.recur-form-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-form-input {\n width: 100%;\n padding: 10px 12px;\n font-size: 16px;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n transition: border-color 0.2s;\n box-sizing: border-box;\n}\n\n.recur-form-input:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.recur-form-input:hover:not(:focus) {\n border-color: #9ca3af;\n}\n\n/* ============================================\n * Card Fields Styles\n * ============================================ */\n.recur-card-field {\n margin-bottom: 16px;\n}\n\n.recur-card-field-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-payuni-iframe {\n height: 36px;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n touch-action: manipulation;\n}\n\n.recur-card-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n column-gap: 16px;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n.recur-card-field-container {\n position: relative;\n touch-action: manipulation;\n}\n\n.recur-card-skeleton {\n position: absolute;\n top: 0;\n left: 0;\n height: 36px;\n width: 100%;\n background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);\n background-size: 200% 100%;\n animation: recur-skeleton-loading 1.5s ease-in-out infinite;\n border-radius: 4px;\n z-index: 1;\n pointer-events: none;\n}\n\n.recur-card-skeleton.hidden {\n display: none;\n}\n\n@keyframes recur-skeleton-loading {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n/* ============================================\n * Submit Button Styles\n * ============================================ */\n.recur-submit-button {\n width: 100%;\n padding: 14px 20px;\n font-size: 16px;\n font-weight: 500;\n color: #ffffff;\n background: #18181b;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n box-sizing: border-box;\n}\n\n.recur-submit-button:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-submit-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.recur-submit-button.loading {\n cursor: wait;\n}\n\n.recur-loading-spinner {\n width: 16px;\n height: 16px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n@keyframes recur-spin {\n to { transform: rotate(360deg); }\n}\n";
1032
+ payment_form_light_default = "/**\n * Payment Form - Light DOM Styles\n * These styles are applied to slotted content in the Light DOM\n * Using BEM naming convention with 'recur-' prefix for isolation\n */\n\n/* ============================================\n * Order Summary Styles\n * ============================================ */\n.recur-order-summary {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n}\n\n.recur-order-summary__row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.recur-order-summary__row--total {\n margin-bottom: 0;\n padding-top: 12px;\n border-top: 1px solid #e2e8f0;\n}\n\n.recur-order-summary__label {\n font-size: 14px;\n color: #4a5568;\n}\n\n.recur-order-summary__value {\n font-size: 14px;\n line-height: 20px;\n font-weight: 500;\n color: #2d3748;\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n.recur-order-summary__total {\n font-size: 18px;\n line-height: 26px;\n font-weight: 700;\n color: #1a202c;\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n/* ============================================\n * Coupon Section Styles\n * ============================================ */\n.recur-coupon {\n padding: 12px 0;\n border-top: 1px solid #e2e8f0;\n margin-top: 12px;\n min-height: 36px;\n display: flex;\n align-items: center;\n}\n\n.recur-coupon__trigger {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n height: 36px;\n background: none;\n border: none;\n padding: 0;\n font-size: 14px;\n line-height: 1;\n color: #718096;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.recur-coupon__trigger:hover {\n color: #4a5568;\n}\n\n.recur-coupon__trigger-icon {\n width: 16px;\n height: 16px;\n}\n\n.recur-coupon__input-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 36px;\n}\n\n.recur-coupon__input {\n flex: 1;\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n text-transform: uppercase;\n background-color: #ffffff;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n outline: none;\n transition: border-color 0.2s, box-shadow 0.2s;\n}\n\n.recur-coupon__input::placeholder {\n text-transform: none;\n}\n\n.recur-coupon__input:hover:not(:focus) {\n border-color: #9ca3af;\n}\n\n.recur-coupon__input:focus {\n border-color: var(--ring, hsl(215 16% 47%));\n outline: 0;\n box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring, hsl(215 16% 47%)) 50%, transparent);\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n.recur-coupon__btn {\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s, opacity 0.2s;\n white-space: nowrap;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.recur-coupon__btn--apply {\n background: #18181b;\n color: white;\n border: none;\n min-width: 52px;\n}\n\n.recur-coupon__btn--apply .recur-coupon__spinner {\n width: 14px;\n height: 14px;\n}\n\n.recur-coupon__btn--apply:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-coupon__btn--apply:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.recur-coupon__btn--cancel {\n background: transparent;\n color: #718096;\n border: 1px solid #d1d5db;\n}\n\n.recur-coupon__btn--cancel:hover {\n background: #f7fafc;\n}\n\n.recur-coupon__error {\n width: 100%;\n margin-top: 8px;\n font-size: 13px;\n color: #dc2626;\n}\n\n.recur-coupon__applied {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 36px;\n}\n\n.recur-coupon__applied-info {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n flex: 1;\n}\n\n.recur-coupon__applied-icon {\n width: 16px;\n height: 16px;\n color: #dc2626;\n flex-shrink: 0;\n}\n\n.recur-coupon__applied-name {\n font-size: 14px;\n font-weight: 500;\n color: #dc2626;\n white-space: nowrap;\n}\n\n.recur-coupon__applied-code {\n font-size: 14px;\n color: #9ca3af;\n white-space: nowrap;\n margin-right: 2px;\n}\n\n.recur-coupon__applied-amount {\n font-size: 14px;\n font-weight: 500;\n color: #dc2626;\n white-space: nowrap;\n font-variant-numeric: tabular-nums;\n flex-shrink: 0;\n margin-left: auto;\n}\n\n.recur-coupon__remove {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #9ca3af;\n border-radius: 4px;\n transition: color 0.2s, background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.recur-coupon__remove:hover {\n color: #6b7280;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.recur-coupon__remove-icon {\n width: 14px;\n height: 14px;\n}\n\n.recur-coupon__spinner {\n width: 14px;\n height: 14px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n/* Discount Row */\n.recur-order-summary__row--discount {\n color: #16a34a;\n}\n\n.recur-order-summary__row--discount .recur-order-summary__value {\n color: #16a34a;\n font-weight: 500;\n}\n\n/* ============================================\n * Customer Info Styles\n * ============================================ */\n.recur-info-display {\n background: #f7fafc;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 8px;\n}\n\n.recur-info-row {\n margin-bottom: 12px;\n}\n\n.recur-info-row:last-child {\n margin-bottom: 0;\n}\n\n.recur-info-label {\n display: block;\n font-size: 12px;\n line-height: 16px;\n color: #718096;\n margin-bottom: 2px;\n}\n\n.recur-info-value {\n display: block;\n font-size: 14px;\n line-height: 20px;\n min-height: 20px;\n color: #2d3748;\n font-weight: 500;\n word-break: break-all;\n}\n\n.recur-form-group {\n margin-bottom: 16px;\n}\n\n.recur-form-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-form-input {\n width: 100%;\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n transition: border-color 0.2s;\n box-sizing: border-box;\n}\n\n.recur-form-input:focus {\n border-color: var(--ring, hsl(215 16% 47%));\n outline: 0;\n box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring, hsl(215 16% 47%)) 50%, transparent);\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n.recur-form-input:hover:not(:focus) {\n border-color: #9ca3af;\n}\n\n/* ============================================\n * Card Fields Styles\n * ============================================ */\n.recur-card-field {\n margin-bottom: 16px;\n}\n\n.recur-card-field-label {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #2d3748;\n margin-bottom: 6px;\n}\n\n.recur-payuni-iframe {\n height: 36px;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n touch-action: manipulation;\n}\n\n.recur-card-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n column-gap: 16px;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n.recur-card-field-container {\n position: relative;\n touch-action: manipulation;\n}\n\n.recur-card-skeleton {\n position: absolute;\n top: 0;\n left: 0;\n height: 36px;\n width: 100%;\n background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);\n background-size: 200% 100%;\n animation: recur-skeleton-loading 1.5s ease-in-out infinite;\n border-radius: 4px;\n z-index: 1;\n pointer-events: none;\n}\n\n.recur-card-skeleton.hidden {\n display: none;\n}\n\n@keyframes recur-skeleton-loading {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n/* ============================================\n * Submit Button Styles\n * ============================================ */\n.recur-submit-button {\n width: 100%;\n padding: 14px 20px;\n font-size: 16px;\n font-weight: 500;\n color: #ffffff;\n background: #18181b;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n box-sizing: border-box;\n}\n\n.recur-submit-button:hover:not(:disabled) {\n background: #27272a;\n}\n\n.recur-submit-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.recur-submit-button.loading {\n cursor: wait;\n}\n\n.recur-loading-spinner {\n width: 16px;\n height: 16px;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: recur-spin 0.6s linear infinite;\n}\n\n@keyframes recur-spin {\n to { transform: rotate(360deg); }\n}\n\n/* ============================================\n * Skeleton Loading Styles\n * ============================================ */\n.recur-skeleton {\n display: inline-block;\n background: linear-gradient(90deg, #f0f0f0 0%, #e8e8e8 50%, #f0f0f0 100%);\n background-size: 200% 100%;\n animation: recur-skeleton-loading 1.5s ease-in-out infinite;\n border-radius: 4px;\n}\n";
1033
1033
  }
1034
1034
  });
1035
1035
 
@@ -1218,7 +1218,25 @@ var init_payment_form = __esm({
1218
1218
  const amount = this.getAttribute("amount");
1219
1219
  const interval = this.getAttribute("interval");
1220
1220
  if (!productName || !amount) {
1221
- return html`<div class="recur-order-summary" style="display: none;"></div>`;
1221
+ return html`
1222
+ <div class="recur-order-summary" id="${this.containerId}-order-summary">
1223
+ <div class="recur-order-summary__row">
1224
+ <span class="recur-order-summary__label">方案</span>
1225
+ <span class="recur-order-summary__value recur-skeleton" style="width: 120px; height: 20px;"></span>
1226
+ </div>
1227
+ <div class="recur-order-summary__row">
1228
+ <span class="recur-order-summary__label">小計</span>
1229
+ <span class="recur-order-summary__value recur-skeleton" style="width: 80px; height: 20px;"></span>
1230
+ </div>
1231
+ <div class="recur-coupon">
1232
+ <span class="recur-skeleton" style="width: 80px; height: 20px;"></span>
1233
+ </div>
1234
+ <div class="recur-order-summary__row recur-order-summary__row--total">
1235
+ <span class="recur-order-summary__label">總計</span>
1236
+ <span class="recur-order-summary__total recur-skeleton" style="width: 100px; height: 26px;"></span>
1237
+ </div>
1238
+ </div>
1239
+ `;
1222
1240
  }
1223
1241
  const intervalMap = {
1224
1242
  "day": "\u65E5",
@@ -1230,35 +1248,26 @@ var init_payment_form = __esm({
1230
1248
  const originalAmount = Number(amount);
1231
1249
  const discountAmount = this._appliedCoupon?.discountAmount || 0;
1232
1250
  const finalAmount = originalAmount - discountAmount;
1251
+ const productDisplay = periodText ? `${productName} / \u6BCF${periodText}` : productName;
1233
1252
  return html`
1234
1253
  <div class="recur-order-summary" id="${this.containerId}-order-summary">
1235
1254
  <div class="recur-order-summary__row">
1236
- <span class="recur-order-summary__label">訂閱方案</span>
1237
- <span class="recur-order-summary__value">${productName}</span>
1255
+ <span class="recur-order-summary__label">方案</span>
1256
+ <span class="recur-order-summary__value">${productDisplay}</span>
1238
1257
  </div>
1239
1258
 
1240
- ${periodText ? html`
1241
- <div class="recur-order-summary__row">
1242
- <span class="recur-order-summary__label">計費週期</span>
1243
- <span class="recur-order-summary__value">每${periodText}</span>
1244
- </div>
1245
- ` : nothing}
1259
+ <!-- 小計 (Subtotal) - always show -->
1260
+ <div class="recur-order-summary__row">
1261
+ <span class="recur-order-summary__label">小計</span>
1262
+ <span class="recur-order-summary__value">NT$ ${originalAmount.toLocaleString()}</span>
1263
+ </div>
1246
1264
 
1265
+ <!-- 優惠碼區塊 (Coupon section with discount amount) -->
1247
1266
  <div class="recur-coupon" id="${this.containerId}-coupon">
1248
1267
  ${this.renderCoupon()}
1249
1268
  </div>
1250
1269
 
1251
- ${discountAmount > 0 ? html`
1252
- <div class="recur-order-summary__row">
1253
- <span class="recur-order-summary__label">小計</span>
1254
- <span class="recur-order-summary__value">NT$ ${originalAmount.toLocaleString()}</span>
1255
- </div>
1256
- <div class="recur-order-summary__row recur-order-summary__row--discount">
1257
- <span class="recur-order-summary__label">折扣</span>
1258
- <span class="recur-order-summary__value">-NT$ ${discountAmount.toLocaleString()}</span>
1259
- </div>
1260
- ` : nothing}
1261
-
1270
+ <!-- 總計 (Total) -->
1262
1271
  <div class="recur-order-summary__row recur-order-summary__row--total">
1263
1272
  <span class="recur-order-summary__label">總計</span>
1264
1273
  <span class="recur-order-summary__total">NT$ ${finalAmount.toLocaleString()}</span>
@@ -1272,26 +1281,24 @@ var init_payment_form = __esm({
1272
1281
  <div class="recur-coupon__applied">
1273
1282
  <div class="recur-coupon__applied-info">
1274
1283
  ${icons.tagApplied}
1275
- <div class="recur-coupon__applied-details">
1276
- <div class="recur-coupon__applied-name">
1277
- ${this._appliedCoupon.couponName || this._appliedCoupon.code}
1278
- </div>
1279
- ${this._appliedCoupon.couponName ? html`
1280
- <div class="recur-coupon__applied-code">代碼:${this._appliedCoupon.code}</div>
1281
- ` : nothing}
1282
- </div>
1284
+ ${this._appliedCoupon.couponName ? html`
1285
+ <span class="recur-coupon__applied-name">${this._appliedCoupon.couponName}</span>
1286
+ <span class="recur-coupon__applied-code">(${this._appliedCoupon.code})</span>
1287
+ ` : html`
1288
+ <span class="recur-coupon__applied-name">${this._appliedCoupon.code}</span>
1289
+ `}
1290
+ <button
1291
+ type="button"
1292
+ class="recur-coupon__remove"
1293
+ ?disabled=${this._couponLoading}
1294
+ @click=${() => this.removeCoupon()}
1295
+ >
1296
+ ${this._couponLoading ? icons.spinner : icons.close}
1297
+ </button>
1283
1298
  </div>
1284
1299
  <span class="recur-coupon__applied-amount">
1285
1300
  -NT$ ${this._appliedCoupon.discountAmount.toLocaleString()}
1286
1301
  </span>
1287
- <button
1288
- type="button"
1289
- class="recur-coupon__remove"
1290
- ?disabled=${this._couponLoading}
1291
- @click=${() => this.removeCoupon()}
1292
- >
1293
- ${this._couponLoading ? icons.spinner : icons.close}
1294
- </button>
1295
1302
  </div>
1296
1303
  `;
1297
1304
  }
@@ -1380,7 +1387,8 @@ var init_payment_form = __esm({
1380
1387
  }
1381
1388
  // Direct DOM manipulation for coupon section updates (avoids lit-html tracking issues)
1382
1389
  updateCouponSectionDOM() {
1383
- const container = document.getElementById(`${this.containerId}-coupon`);
1390
+ const containerId = `${this.containerId}-coupon`;
1391
+ const container = document.getElementById(containerId);
1384
1392
  if (!container) return;
1385
1393
  if (this._appliedCoupon) {
1386
1394
  container.innerHTML = this.getCouponAppliedHTML();
@@ -1437,22 +1445,19 @@ var init_payment_form = __esm({
1437
1445
  }
1438
1446
  getCouponAppliedHTML() {
1439
1447
  const coupon = this._appliedCoupon;
1440
- const codeHTML = coupon.couponName ? `<div class="recur-coupon__applied-code">\u4EE3\u78BC\uFF1A${coupon.code}</div>` : "";
1448
+ 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>`;
1441
1449
  return `
1442
1450
  <div class="recur-coupon__applied">
1443
1451
  <div class="recur-coupon__applied-info">
1444
1452
  <svg class="recur-coupon__applied-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1445
1453
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
1446
1454
  </svg>
1447
- <div class="recur-coupon__applied-details">
1448
- <div class="recur-coupon__applied-name">${coupon.couponName || coupon.code}</div>
1449
- ${codeHTML}
1450
- </div>
1455
+ ${nameHTML}
1456
+ <button type="button" class="recur-coupon__remove" ${this._couponLoading ? "disabled" : ""}>
1457
+ ${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>'}
1458
+ </button>
1451
1459
  </div>
1452
1460
  <span class="recur-coupon__applied-amount">-NT$ ${coupon.discountAmount.toLocaleString()}</span>
1453
- <button type="button" class="recur-coupon__remove" ${this._couponLoading ? "disabled" : ""}>
1454
- ${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>'}
1455
- </button>
1456
1461
  </div>
1457
1462
  `;
1458
1463
  }
@@ -1479,31 +1484,7 @@ var init_payment_form = __esm({
1479
1484
  const amount = Number(this.getAttribute("amount") || 0);
1480
1485
  const discountAmount = this._appliedCoupon?.discountAmount || 0;
1481
1486
  const finalAmount = amount - discountAmount;
1482
- let discountRow = summaryContainer.querySelector(".recur-order-summary__row--discount");
1483
1487
  const totalRow = summaryContainer.querySelector(".recur-order-summary__row--total");
1484
- if (discountAmount > 0) {
1485
- if (!discountRow && totalRow) {
1486
- const subtotalHTML = `
1487
- <div class="recur-order-summary__row">
1488
- <span class="recur-order-summary__label">\u5C0F\u8A08</span>
1489
- <span class="recur-order-summary__value">NT$ ${amount.toLocaleString()}</span>
1490
- </div>
1491
- `;
1492
- const discountHTML = `
1493
- <div class="recur-order-summary__row recur-order-summary__row--discount">
1494
- <span class="recur-order-summary__label">\u6298\u6263</span>
1495
- <span class="recur-order-summary__value">-NT$ ${discountAmount.toLocaleString()}</span>
1496
- </div>
1497
- `;
1498
- totalRow.insertAdjacentHTML("beforebegin", subtotalHTML + discountHTML);
1499
- }
1500
- } else {
1501
- const subtotalRow = summaryContainer.querySelector(".recur-order-summary__row:not(.recur-order-summary__row--total):last-of-type");
1502
- discountRow?.remove();
1503
- if (subtotalRow?.querySelector(".recur-order-summary__label")?.textContent === "\u5C0F\u8A08") {
1504
- subtotalRow.remove();
1505
- }
1506
- }
1507
1488
  const totalValue = totalRow?.querySelector(".recur-order-summary__total");
1508
1489
  if (totalValue) {
1509
1490
  totalValue.textContent = `NT$ ${finalAmount.toLocaleString()}`;
@@ -1531,7 +1512,7 @@ var init_payment_form = __esm({
1531
1512
  this._couponError = null;
1532
1513
  this.updateCouponSectionDOM();
1533
1514
  try {
1534
- const response = await fetch(`${apiBaseUrl}/api/checkout/${checkoutId}/coupon`, {
1515
+ const response = await fetch(`${apiBaseUrl}/v1/checkouts/${checkoutId}/coupon`, {
1535
1516
  method: "POST",
1536
1517
  headers: { "Content-Type": "application/json" },
1537
1518
  body: JSON.stringify({ code })
@@ -1577,7 +1558,7 @@ var init_payment_form = __esm({
1577
1558
  this._couponLoading = true;
1578
1559
  this.updateCouponSectionDOM();
1579
1560
  try {
1580
- const response = await fetch(`${apiBaseUrl}/api/checkout/${checkoutId}/coupon`, {
1561
+ const response = await fetch(`${apiBaseUrl}/v1/checkouts/${checkoutId}/coupon`, {
1581
1562
  method: "DELETE"
1582
1563
  });
1583
1564
  if (!response.ok) {
@@ -2559,7 +2540,7 @@ function toCamelCase(obj) {
2559
2540
 
2560
2541
  // package.json
2561
2542
  var package_default = {
2562
- version: "0.9.9"};
2543
+ version: "0.9.12"};
2563
2544
  var SDK_VERSION = package_default.version;
2564
2545
  var SDK_TYPE = "react";
2565
2546
  var RecurContext = createContext(null);
@@ -2875,6 +2856,10 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2875
2856
  container.innerHTML = "";
2876
2857
  const paymentForm = document.createElement("recur-payment-form");
2877
2858
  paymentForm.setAttribute("container-id", containerElementId);
2859
+ if (checkoutResult.checkout?.id) {
2860
+ paymentForm.setAttribute("checkout-id", checkoutResult.checkout.id);
2861
+ }
2862
+ paymentForm.setAttribute("api-base-url", baseUrl);
2878
2863
  if (options.customerName) {
2879
2864
  paymentForm.setAttribute("customer-name", options.customerName);
2880
2865
  }
@@ -2891,7 +2876,6 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2891
2876
  paymentForm.setAttribute("interval", checkoutResult.product.interval);
2892
2877
  }
2893
2878
  const customStyles = `
2894
- /* PAYUNi SDK focus \u6A23\u5F0F - shadcn \u98A8\u683C */
2895
2879
  .form-input-focus {
2896
2880
  border-color: var(--ring, hsl(215 16% 47%)) !important;
2897
2881
  outline: 0 !important;