recur-tw 0.9.12 → 0.9.13

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.js CHANGED
@@ -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 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";
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-wrapper {\n position: relative;\n flex: 1;\n}\n\n.recur-coupon__input {\n width: 100%;\n height: 36px;\n padding: 0 32px 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__clear {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #9ca3af;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.2s;\n}\n\n.recur-coupon__clear:hover {\n color: #6b7280;\n}\n\n.recur-coupon__clear-icon {\n width: 16px;\n height: 16px;\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__error {\n width: 100%;\n margin-top: 8px;\n font-size: 13px;\n color: #dc2626;\n}\n\n.recur-coupon__applied-wrapper {\n width: 100%;\n}\n\n.recur-coupon__description {\n font-size: 12px;\n color: #6b7280;\n margin: 4px 0 0 22px;\n}\n\n.recur-coupon__bonus {\n display: flex;\n align-items: center;\n gap: 6px;\n background: #dcfce7;\n border-radius: 6px;\n padding: 8px 12px;\n margin-top: 8px;\n font-size: 12px;\n color: #15803d;\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
 
@@ -1063,6 +1063,11 @@ var init_payment_form = __esm({
1063
1063
  <svg class="recur-coupon__remove-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1064
1064
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
1065
1065
  </svg>
1066
+ `,
1067
+ clearInput: html`
1068
+ <svg class="recur-coupon__clear-icon" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1069
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
1070
+ </svg>
1066
1071
  `,
1067
1072
  spinner: html`<span class="recur-coupon__spinner"></span>`
1068
1073
  };
@@ -1275,30 +1280,106 @@ var init_payment_form = __esm({
1275
1280
  </div>
1276
1281
  `;
1277
1282
  }
1283
+ // Helper to get interval text in Chinese
1284
+ getIntervalText(interval, count) {
1285
+ if (!interval) return "";
1286
+ const countText = count && count > 1 ? count.toString() : "";
1287
+ switch (interval.toUpperCase()) {
1288
+ case "MONTH":
1289
+ return `${countText}\u6708`;
1290
+ case "YEAR":
1291
+ return `${countText}\u5E74`;
1292
+ case "WEEK":
1293
+ return `${countText}\u9031`;
1294
+ case "DAY":
1295
+ return `${countText}\u5929`;
1296
+ default:
1297
+ return "";
1298
+ }
1299
+ }
1300
+ // Get discount description based on type and duration
1301
+ getDiscountDescription() {
1302
+ if (!this._appliedCoupon) return null;
1303
+ const { discountType, duration, durationMonths, productPrice, productInterval, productIntervalCount } = this._appliedCoupon;
1304
+ const intervalText = this.getIntervalText(productInterval, productIntervalCount);
1305
+ const originalPriceText = productPrice && intervalText ? `NT$ ${productPrice.toLocaleString()}/${intervalText}` : productPrice ? `NT$ ${productPrice.toLocaleString()}` : "";
1306
+ const amount = parseInt(this.getAttribute("amount") || "0", 10);
1307
+ const finalAmount = amount - this._appliedCoupon.discountAmount;
1308
+ if (discountType === "FIRST_PERIOD_PRICE") {
1309
+ if (originalPriceText) {
1310
+ return `\u9996\u671F\u53EA\u9700 NT$ ${finalAmount.toLocaleString()}\uFF0C\u4E4B\u5F8C ${originalPriceText}`;
1311
+ }
1312
+ return `\u9996\u671F\u53EA\u9700 NT$ ${finalAmount.toLocaleString()}`;
1313
+ }
1314
+ if (duration) {
1315
+ switch (duration) {
1316
+ case "ONCE":
1317
+ if (originalPriceText) {
1318
+ return `\u9996\u671F\u6298\u6263\uFF0C\u4E4B\u5F8C ${originalPriceText}`;
1319
+ }
1320
+ return "\u50C5\u9650\u9996\u671F";
1321
+ case "REPEATING":
1322
+ if (durationMonths) {
1323
+ return `\u524D ${durationMonths} \u671F\u4EAB\u512A\u60E0\uFF0C\u4E4B\u5F8C\u6062\u5FA9\u539F\u50F9`;
1324
+ }
1325
+ return null;
1326
+ case "FOREVER":
1327
+ return "\u7D42\u8EAB\u512A\u60E0";
1328
+ default:
1329
+ return null;
1330
+ }
1331
+ }
1332
+ return null;
1333
+ }
1334
+ // Get bonus description
1335
+ getBonusDescription() {
1336
+ if (!this._appliedCoupon) return null;
1337
+ const parts = [];
1338
+ if (this._appliedCoupon.bonusTrialDays) {
1339
+ parts.push(`\u5EF6\u9577\u8A66\u7528 ${this._appliedCoupon.bonusTrialDays} \u5929`);
1340
+ }
1341
+ if (this._appliedCoupon.bonusMonths) {
1342
+ parts.push(`\u52A0\u9001 ${this._appliedCoupon.bonusMonths} \u500B\u6708`);
1343
+ }
1344
+ return parts.length > 0 ? parts.join("\u3001") : null;
1345
+ }
1278
1346
  renderCoupon() {
1279
1347
  if (this._appliedCoupon) {
1348
+ const discountDescription = this.getDiscountDescription();
1349
+ const bonusDescription = this.getBonusDescription();
1280
1350
  return html`
1281
- <div class="recur-coupon__applied">
1282
- <div class="recur-coupon__applied-info">
1283
- ${icons.tagApplied}
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>
1351
+ <div class="recur-coupon__applied-wrapper">
1352
+ <div class="recur-coupon__applied">
1353
+ <div class="recur-coupon__applied-info">
1354
+ ${icons.tagApplied}
1355
+ ${this._appliedCoupon.couponName ? html`
1356
+ <span class="recur-coupon__applied-name">${this._appliedCoupon.couponName}</span>
1357
+ <span class="recur-coupon__applied-code">(${this._appliedCoupon.code})</span>
1358
+ ` : html`
1359
+ <span class="recur-coupon__applied-name">${this._appliedCoupon.code}</span>
1360
+ `}
1361
+ <button
1362
+ type="button"
1363
+ class="recur-coupon__remove"
1364
+ ?disabled=${this._couponLoading}
1365
+ @click=${() => this.removeCoupon()}
1366
+ >
1367
+ ${this._couponLoading ? icons.spinner : icons.close}
1368
+ </button>
1369
+ </div>
1370
+ <span class="recur-coupon__applied-amount">
1371
+ -NT$ ${this._appliedCoupon.discountAmount.toLocaleString()}
1372
+ </span>
1298
1373
  </div>
1299
- <span class="recur-coupon__applied-amount">
1300
- -NT$ ${this._appliedCoupon.discountAmount.toLocaleString()}
1301
- </span>
1374
+ ${discountDescription ? html`
1375
+ <p class="recur-coupon__description">${discountDescription}</p>
1376
+ ` : nothing}
1377
+ ${bonusDescription ? html`
1378
+ <div class="recur-coupon__bonus">
1379
+ <span>✨</span>
1380
+ <span>${bonusDescription}</span>
1381
+ </div>
1382
+ ` : nothing}
1302
1383
  </div>
1303
1384
  `;
1304
1385
  }
@@ -1306,16 +1387,28 @@ var init_payment_form = __esm({
1306
1387
  return html`
1307
1388
  <div style="width: 100%;">
1308
1389
  <div class="recur-coupon__input-row">
1309
- <input
1310
- type="text"
1311
- class="recur-coupon__input"
1312
- id="${this.containerId}-coupon-input"
1313
- placeholder="輸入優惠碼"
1314
- .value=${this._couponCode}
1315
- ?disabled=${this._couponLoading}
1316
- @input=${(e) => this.handleCouponInputChange(e)}
1317
- @keydown=${(e) => this.handleCouponKeydown(e)}
1318
- />
1390
+ <div class="recur-coupon__input-wrapper">
1391
+ <input
1392
+ type="text"
1393
+ class="recur-coupon__input"
1394
+ id="${this.containerId}-coupon-input"
1395
+ placeholder="輸入優惠碼"
1396
+ .value=${this._couponCode}
1397
+ ?disabled=${this._couponLoading}
1398
+ @input=${(e) => this.handleCouponInputChange(e)}
1399
+ @keydown=${(e) => this.handleCouponKeydown(e)}
1400
+ />
1401
+ ${this._couponCode && !this._couponLoading ? html`
1402
+ <button
1403
+ type="button"
1404
+ class="recur-coupon__clear"
1405
+ @click=${() => this.clearCouponInput()}
1406
+ aria-label="清除"
1407
+ >
1408
+ ${icons.clearInput}
1409
+ </button>
1410
+ ` : nothing}
1411
+ </div>
1319
1412
  <button
1320
1413
  type="button"
1321
1414
  class="recur-coupon__btn recur-coupon__btn--apply"
@@ -1324,14 +1417,6 @@ var init_payment_form = __esm({
1324
1417
  >
1325
1418
  ${this._couponLoading ? icons.spinner : "\u5957\u7528"}
1326
1419
  </button>
1327
- <button
1328
- type="button"
1329
- class="recur-coupon__btn recur-coupon__btn--cancel"
1330
- ?disabled=${this._couponLoading}
1331
- @click=${() => this.cancelCouponInput()}
1332
- >
1333
- 取消
1334
- </button>
1335
1420
  </div>
1336
1421
  ${this._couponError ? html`
1337
1422
  <div class="recur-coupon__error">${this._couponError}</div>
@@ -1366,6 +1451,15 @@ var init_payment_form = __esm({
1366
1451
  this._couponError = null;
1367
1452
  this.updateCouponSectionDOM();
1368
1453
  }
1454
+ clearCouponInput() {
1455
+ this._couponCode = "";
1456
+ this._couponError = null;
1457
+ this.updateCouponSectionDOM();
1458
+ requestAnimationFrame(() => {
1459
+ const input = document.getElementById(`${this.containerId}-coupon-input`);
1460
+ input?.focus();
1461
+ });
1462
+ }
1369
1463
  handleCouponInputChange(e) {
1370
1464
  this._couponCode = e.target.value.toUpperCase();
1371
1465
  this._couponError = null;
@@ -1413,17 +1507,25 @@ var init_payment_form = __esm({
1413
1507
  }
1414
1508
  getCouponInputHTML() {
1415
1509
  const errorHTML = this._couponError ? `<div class="recur-coupon__error">${this._couponError}</div>` : "";
1510
+ const clearBtnHTML = this._couponCode && !this._couponLoading ? `<button type="button" class="recur-coupon__clear" aria-label="\u6E05\u9664">
1511
+ <svg class="recur-coupon__clear-icon" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1512
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
1513
+ </svg>
1514
+ </button>` : "";
1416
1515
  return `
1417
1516
  <div style="width: 100%;">
1418
1517
  <div class="recur-coupon__input-row">
1419
- <input
1420
- type="text"
1421
- class="recur-coupon__input"
1422
- id="${this.containerId}-coupon-input"
1423
- placeholder="\u8F38\u5165\u512A\u60E0\u78BC"
1424
- value="${this._couponCode}"
1425
- ${this._couponLoading ? "disabled" : ""}
1426
- />
1518
+ <div class="recur-coupon__input-wrapper">
1519
+ <input
1520
+ type="text"
1521
+ class="recur-coupon__input"
1522
+ id="${this.containerId}-coupon-input"
1523
+ placeholder="\u8F38\u5165\u512A\u60E0\u78BC"
1524
+ value="${this._couponCode}"
1525
+ ${this._couponLoading ? "disabled" : ""}
1526
+ />
1527
+ ${clearBtnHTML}
1528
+ </div>
1427
1529
  <button
1428
1530
  type="button"
1429
1531
  class="recur-coupon__btn recur-coupon__btn--apply"
@@ -1431,13 +1533,6 @@ var init_payment_form = __esm({
1431
1533
  >
1432
1534
  ${this._couponLoading ? '<span class="recur-coupon__spinner"></span>' : "\u5957\u7528"}
1433
1535
  </button>
1434
- <button
1435
- type="button"
1436
- class="recur-coupon__btn recur-coupon__btn--cancel"
1437
- ${this._couponLoading ? "disabled" : ""}
1438
- >
1439
- \u53D6\u6D88
1440
- </button>
1441
1536
  </div>
1442
1537
  ${errorHTML}
1443
1538
  </div>
@@ -1446,18 +1541,26 @@ var init_payment_form = __esm({
1446
1541
  getCouponAppliedHTML() {
1447
1542
  const coupon = this._appliedCoupon;
1448
1543
  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>`;
1544
+ const discountDescription = this.getDiscountDescription();
1545
+ const bonusDescription = this.getBonusDescription();
1546
+ const descriptionHTML = discountDescription ? `<p class="recur-coupon__description">${discountDescription}</p>` : "";
1547
+ const bonusHTML = bonusDescription ? `<div class="recur-coupon__bonus"><span>\u2728</span><span>${bonusDescription}</span></div>` : "";
1449
1548
  return `
1450
- <div class="recur-coupon__applied">
1451
- <div class="recur-coupon__applied-info">
1452
- <svg class="recur-coupon__applied-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
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" />
1454
- </svg>
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>
1549
+ <div class="recur-coupon__applied-wrapper">
1550
+ <div class="recur-coupon__applied">
1551
+ <div class="recur-coupon__applied-info">
1552
+ <svg class="recur-coupon__applied-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1553
+ <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" />
1554
+ </svg>
1555
+ ${nameHTML}
1556
+ <button type="button" class="recur-coupon__remove" ${this._couponLoading ? "disabled" : ""}>
1557
+ ${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>'}
1558
+ </button>
1559
+ </div>
1560
+ <span class="recur-coupon__applied-amount">-NT$ ${coupon.discountAmount.toLocaleString()}</span>
1459
1561
  </div>
1460
- <span class="recur-coupon__applied-amount">-NT$ ${coupon.discountAmount.toLocaleString()}</span>
1562
+ ${descriptionHTML}
1563
+ ${bonusHTML}
1461
1564
  </div>
1462
1565
  `;
1463
1566
  }
@@ -1468,11 +1571,11 @@ var init_payment_form = __esm({
1468
1571
  bindCouponInputEvents(container) {
1469
1572
  const input = container.querySelector(".recur-coupon__input");
1470
1573
  const applyBtn = container.querySelector(".recur-coupon__btn--apply");
1471
- const cancelBtn = container.querySelector(".recur-coupon__btn--cancel");
1574
+ const clearBtn = container.querySelector(".recur-coupon__clear");
1472
1575
  input?.addEventListener("input", (e) => this.handleCouponInputChange(e));
1473
1576
  input?.addEventListener("keydown", (e) => this.handleCouponKeydown(e));
1474
1577
  applyBtn?.addEventListener("click", () => this.applyCoupon());
1475
- cancelBtn?.addEventListener("click", () => this.cancelCouponInput());
1578
+ clearBtn?.addEventListener("click", () => this.clearCouponInput());
1476
1579
  }
1477
1580
  bindCouponAppliedEvents(container) {
1478
1581
  const removeBtn = container.querySelector(".recur-coupon__remove");
@@ -1532,7 +1635,10 @@ var init_payment_form = __esm({
1532
1635
  duration: data.discount.duration,
1533
1636
  durationMonths: data.discount.durationMonths,
1534
1637
  bonusTrialDays: data.discount.bonusTrialDays,
1535
- bonusMonths: data.discount.bonusMonths
1638
+ bonusMonths: data.discount.bonusMonths,
1639
+ productInterval: data.discount.productInterval,
1640
+ productIntervalCount: data.discount.productIntervalCount,
1641
+ productPrice: data.discount.productPrice
1536
1642
  };
1537
1643
  this._showCouponInput = false;
1538
1644
  this._couponCode = "";
@@ -2540,7 +2646,7 @@ function toCamelCase(obj) {
2540
2646
 
2541
2647
  // package.json
2542
2648
  var package_default = {
2543
- version: "0.9.12"};
2649
+ version: "0.9.13"};
2544
2650
  var SDK_VERSION = package_default.version;
2545
2651
  var SDK_TYPE = "react";
2546
2652
  var RecurContext = createContext(null);