recur-tw 0.9.11 → 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.cjs +182 -91
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +182 -91
- package/dist/recur.umd.js +204 -142
- package/dist/server.cjs +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
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"
|
|
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"
|
|
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 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 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: #
|
|
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
|
};
|
|
@@ -1218,19 +1223,12 @@ var init_payment_form = __esm({
|
|
|
1218
1223
|
const amount = this.getAttribute("amount");
|
|
1219
1224
|
const interval = this.getAttribute("interval");
|
|
1220
1225
|
if (!productName || !amount) {
|
|
1221
|
-
const isSubscription2 = !!interval;
|
|
1222
1226
|
return html`
|
|
1223
1227
|
<div class="recur-order-summary" id="${this.containerId}-order-summary">
|
|
1224
1228
|
<div class="recur-order-summary__row">
|
|
1225
|
-
<span class="recur-order-summary__label"
|
|
1226
|
-
<span class="recur-order-summary__value recur-skeleton" style="width:
|
|
1229
|
+
<span class="recur-order-summary__label">方案</span>
|
|
1230
|
+
<span class="recur-order-summary__value recur-skeleton" style="width: 120px; height: 20px;"></span>
|
|
1227
1231
|
</div>
|
|
1228
|
-
${isSubscription2 ? html`
|
|
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: 40px; height: 20px;"></span>
|
|
1232
|
-
</div>
|
|
1233
|
-
` : nothing}
|
|
1234
1232
|
<div class="recur-order-summary__row">
|
|
1235
1233
|
<span class="recur-order-summary__label">小計</span>
|
|
1236
1234
|
<span class="recur-order-summary__value recur-skeleton" style="width: 80px; height: 20px;"></span>
|
|
@@ -1255,21 +1253,14 @@ var init_payment_form = __esm({
|
|
|
1255
1253
|
const originalAmount = Number(amount);
|
|
1256
1254
|
const discountAmount = this._appliedCoupon?.discountAmount || 0;
|
|
1257
1255
|
const finalAmount = originalAmount - discountAmount;
|
|
1258
|
-
const
|
|
1256
|
+
const productDisplay = periodText ? `${productName} / \u6BCF${periodText}` : productName;
|
|
1259
1257
|
return html`
|
|
1260
1258
|
<div class="recur-order-summary" id="${this.containerId}-order-summary">
|
|
1261
1259
|
<div class="recur-order-summary__row">
|
|
1262
|
-
<span class="recur-order-summary__label"
|
|
1263
|
-
<span class="recur-order-summary__value">${
|
|
1260
|
+
<span class="recur-order-summary__label">方案</span>
|
|
1261
|
+
<span class="recur-order-summary__value">${productDisplay}</span>
|
|
1264
1262
|
</div>
|
|
1265
1263
|
|
|
1266
|
-
${isSubscription ? html`
|
|
1267
|
-
<div class="recur-order-summary__row">
|
|
1268
|
-
<span class="recur-order-summary__label">計費週期</span>
|
|
1269
|
-
<span class="recur-order-summary__value">每${periodText}</span>
|
|
1270
|
-
</div>
|
|
1271
|
-
` : nothing}
|
|
1272
|
-
|
|
1273
1264
|
<!-- 小計 (Subtotal) - always show -->
|
|
1274
1265
|
<div class="recur-order-summary__row">
|
|
1275
1266
|
<span class="recur-order-summary__label">小計</span>
|
|
@@ -1289,30 +1280,106 @@ var init_payment_form = __esm({
|
|
|
1289
1280
|
</div>
|
|
1290
1281
|
`;
|
|
1291
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
|
+
}
|
|
1292
1346
|
renderCoupon() {
|
|
1293
1347
|
if (this._appliedCoupon) {
|
|
1348
|
+
const discountDescription = this.getDiscountDescription();
|
|
1349
|
+
const bonusDescription = this.getBonusDescription();
|
|
1294
1350
|
return html`
|
|
1295
|
-
<div class="recur-coupon__applied">
|
|
1296
|
-
<div class="recur-coupon__applied
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
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>
|
|
1312
1373
|
</div>
|
|
1313
|
-
|
|
1314
|
-
-
|
|
1315
|
-
|
|
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}
|
|
1316
1383
|
</div>
|
|
1317
1384
|
`;
|
|
1318
1385
|
}
|
|
@@ -1320,16 +1387,28 @@ var init_payment_form = __esm({
|
|
|
1320
1387
|
return html`
|
|
1321
1388
|
<div style="width: 100%;">
|
|
1322
1389
|
<div class="recur-coupon__input-row">
|
|
1323
|
-
<
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
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>
|
|
1333
1412
|
<button
|
|
1334
1413
|
type="button"
|
|
1335
1414
|
class="recur-coupon__btn recur-coupon__btn--apply"
|
|
@@ -1338,14 +1417,6 @@ var init_payment_form = __esm({
|
|
|
1338
1417
|
>
|
|
1339
1418
|
${this._couponLoading ? icons.spinner : "\u5957\u7528"}
|
|
1340
1419
|
</button>
|
|
1341
|
-
<button
|
|
1342
|
-
type="button"
|
|
1343
|
-
class="recur-coupon__btn recur-coupon__btn--cancel"
|
|
1344
|
-
?disabled=${this._couponLoading}
|
|
1345
|
-
@click=${() => this.cancelCouponInput()}
|
|
1346
|
-
>
|
|
1347
|
-
取消
|
|
1348
|
-
</button>
|
|
1349
1420
|
</div>
|
|
1350
1421
|
${this._couponError ? html`
|
|
1351
1422
|
<div class="recur-coupon__error">${this._couponError}</div>
|
|
@@ -1380,6 +1451,15 @@ var init_payment_form = __esm({
|
|
|
1380
1451
|
this._couponError = null;
|
|
1381
1452
|
this.updateCouponSectionDOM();
|
|
1382
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
|
+
}
|
|
1383
1463
|
handleCouponInputChange(e) {
|
|
1384
1464
|
this._couponCode = e.target.value.toUpperCase();
|
|
1385
1465
|
this._couponError = null;
|
|
@@ -1427,17 +1507,25 @@ var init_payment_form = __esm({
|
|
|
1427
1507
|
}
|
|
1428
1508
|
getCouponInputHTML() {
|
|
1429
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>` : "";
|
|
1430
1515
|
return `
|
|
1431
1516
|
<div style="width: 100%;">
|
|
1432
1517
|
<div class="recur-coupon__input-row">
|
|
1433
|
-
<
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
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>
|
|
1441
1529
|
<button
|
|
1442
1530
|
type="button"
|
|
1443
1531
|
class="recur-coupon__btn recur-coupon__btn--apply"
|
|
@@ -1445,13 +1533,6 @@ var init_payment_form = __esm({
|
|
|
1445
1533
|
>
|
|
1446
1534
|
${this._couponLoading ? '<span class="recur-coupon__spinner"></span>' : "\u5957\u7528"}
|
|
1447
1535
|
</button>
|
|
1448
|
-
<button
|
|
1449
|
-
type="button"
|
|
1450
|
-
class="recur-coupon__btn recur-coupon__btn--cancel"
|
|
1451
|
-
${this._couponLoading ? "disabled" : ""}
|
|
1452
|
-
>
|
|
1453
|
-
\u53D6\u6D88
|
|
1454
|
-
</button>
|
|
1455
1536
|
</div>
|
|
1456
1537
|
${errorHTML}
|
|
1457
1538
|
</div>
|
|
@@ -1460,18 +1541,26 @@ var init_payment_form = __esm({
|
|
|
1460
1541
|
getCouponAppliedHTML() {
|
|
1461
1542
|
const coupon = this._appliedCoupon;
|
|
1462
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>` : "";
|
|
1463
1548
|
return `
|
|
1464
|
-
<div class="recur-coupon__applied">
|
|
1465
|
-
<div class="recur-coupon__applied
|
|
1466
|
-
<
|
|
1467
|
-
<
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
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>
|
|
1473
1561
|
</div>
|
|
1474
|
-
|
|
1562
|
+
${descriptionHTML}
|
|
1563
|
+
${bonusHTML}
|
|
1475
1564
|
</div>
|
|
1476
1565
|
`;
|
|
1477
1566
|
}
|
|
@@ -1482,11 +1571,11 @@ var init_payment_form = __esm({
|
|
|
1482
1571
|
bindCouponInputEvents(container) {
|
|
1483
1572
|
const input = container.querySelector(".recur-coupon__input");
|
|
1484
1573
|
const applyBtn = container.querySelector(".recur-coupon__btn--apply");
|
|
1485
|
-
const
|
|
1574
|
+
const clearBtn = container.querySelector(".recur-coupon__clear");
|
|
1486
1575
|
input?.addEventListener("input", (e) => this.handleCouponInputChange(e));
|
|
1487
1576
|
input?.addEventListener("keydown", (e) => this.handleCouponKeydown(e));
|
|
1488
1577
|
applyBtn?.addEventListener("click", () => this.applyCoupon());
|
|
1489
|
-
|
|
1578
|
+
clearBtn?.addEventListener("click", () => this.clearCouponInput());
|
|
1490
1579
|
}
|
|
1491
1580
|
bindCouponAppliedEvents(container) {
|
|
1492
1581
|
const removeBtn = container.querySelector(".recur-coupon__remove");
|
|
@@ -1546,7 +1635,10 @@ var init_payment_form = __esm({
|
|
|
1546
1635
|
duration: data.discount.duration,
|
|
1547
1636
|
durationMonths: data.discount.durationMonths,
|
|
1548
1637
|
bonusTrialDays: data.discount.bonusTrialDays,
|
|
1549
|
-
bonusMonths: data.discount.bonusMonths
|
|
1638
|
+
bonusMonths: data.discount.bonusMonths,
|
|
1639
|
+
productInterval: data.discount.productInterval,
|
|
1640
|
+
productIntervalCount: data.discount.productIntervalCount,
|
|
1641
|
+
productPrice: data.discount.productPrice
|
|
1550
1642
|
};
|
|
1551
1643
|
this._showCouponInput = false;
|
|
1552
1644
|
this._couponCode = "";
|
|
@@ -2554,7 +2646,7 @@ function toCamelCase(obj) {
|
|
|
2554
2646
|
|
|
2555
2647
|
// package.json
|
|
2556
2648
|
var package_default = {
|
|
2557
|
-
version: "0.9.
|
|
2649
|
+
version: "0.9.13"};
|
|
2558
2650
|
var SDK_VERSION = package_default.version;
|
|
2559
2651
|
var SDK_TYPE = "react";
|
|
2560
2652
|
var RecurContext = createContext(null);
|
|
@@ -2890,7 +2982,6 @@ function RecurProvider({ children, config: initialConfig = {} }) {
|
|
|
2890
2982
|
paymentForm.setAttribute("interval", checkoutResult.product.interval);
|
|
2891
2983
|
}
|
|
2892
2984
|
const customStyles = `
|
|
2893
|
-
/* PAYUNi SDK focus \u6A23\u5F0F - shadcn \u98A8\u683C */
|
|
2894
2985
|
.form-input-focus {
|
|
2895
2986
|
border-color: var(--ring, hsl(215 16% 47%)) !important;
|
|
2896
2987
|
outline: 0 !important;
|