@economist/web-apple-pay 1.6.1 → 1.7.0

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
@@ -439,7 +439,91 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
439
439
  };
440
440
 
441
441
  // src/templates/apple-pay-button.template.html
442
- var apple_pay_button_template_default = '<style>\n /* Use CSS variables for layout so parent walls can easily override placement and sizing */\n teg-apple-pay-button {\n display: block;\n margin: var(--apple-pay-margin, 0);\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: var(--apple-pay-height, 2.75rem);\n background-color: #000;\n color: #fff;\n border: none;\n border-radius: var(--apple-pay-border-radius, 1.375rem);\n cursor: pointer;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-weight: 500;\n }\n\n teg-apple-pay-button .apple-pay-btn svg {\n flex-shrink: 0;\n display: block;\n }\n</style>\n\n<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">\n <button\n class="apple-pay-btn"\n type="button"\n aria-label="Pay with Apple Pay"\n data-analytics="paywall:apple-pay-checkout"\n >\n <svg width="51" height="22" aria-label="Apple Pay" role="img">\n <use href="#apple-pay-logo" />\n </svg>\n </button>\n</div>\n';
442
+ var apple_pay_button_template_default = `<style>
443
+ /* Use CSS variables for layout so parent walls can easily override placement and sizing */
444
+ teg-apple-pay-button {
445
+ display: block;
446
+ margin: var(--apple-pay-margin, 0);
447
+ width: 100%;
448
+ height: 100%;
449
+ }
450
+
451
+ teg-apple-pay-button .apple-pay-container {
452
+ display: flex;
453
+ flex-direction: column;
454
+ align-items: stretch;
455
+ width: 100%;
456
+ height: 100%;
457
+ }
458
+
459
+ teg-apple-pay-button .apple-pay-btn {
460
+ display: flex;
461
+ align-items: center;
462
+ justify-content: center;
463
+ gap: 0.375rem;
464
+ width: 100%;
465
+ min-width: 0;
466
+ height: 100%;
467
+ min-height: var(--apple-pay-height, 2.75rem);
468
+ background-color: #000;
469
+ color: #fff;
470
+ border: none;
471
+ border-radius: var(--apple-pay-border-radius, 1.375rem);
472
+ cursor: pointer;
473
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
474
+ font-size: 1.0625rem;
475
+ font-weight: 500;
476
+ }
477
+
478
+ teg-apple-pay-button .apple-pay-btn svg {
479
+ flex-shrink: 0;
480
+ display: block;
481
+ }
482
+
483
+ teg-apple-pay-button .apple-pay-btn.wap-loading {
484
+ position: relative;
485
+ cursor: default;
486
+ }
487
+
488
+ teg-apple-pay-button .apple-pay-btn.wap-loading svg {
489
+ visibility: hidden;
490
+ }
491
+
492
+ teg-apple-pay-button .apple-pay-btn.wap-loading::after {
493
+ content: '';
494
+ position: absolute;
495
+ left: 50%;
496
+ top: 50%;
497
+ margin-left: -0.625rem;
498
+ margin-top: -0.625rem;
499
+ width: 1.25rem;
500
+ height: 1.25rem;
501
+ border: 2px solid rgba(255, 255, 255, 0.2);
502
+ border-top-color: #fff;
503
+ border-radius: 50%;
504
+ animation: wap-button-spinner 0.8s linear infinite;
505
+ }
506
+
507
+ @keyframes wap-button-spinner {
508
+ to {
509
+ transform: rotate(360deg);
510
+ }
511
+ }
512
+ </style>
513
+
514
+ <div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
515
+ <button
516
+ class="apple-pay-btn"
517
+ type="button"
518
+ aria-label="Pay with Apple Pay"
519
+ data-analytics="paywall:apple-pay-checkout"
520
+ >
521
+ <svg width="51" height="22" aria-label="Apple Pay" role="img">
522
+ <use href="#apple-pay-logo" />
523
+ </svg>
524
+ </button>
525
+ </div>
526
+ `;
443
527
 
444
528
  // src/clients/payment-checkout/config.ts
445
529
  var runtimeConfig = null;
@@ -1407,14 +1491,16 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1407
1491
  async #run() {
1408
1492
  try {
1409
1493
  if (await this.#checkAvailability()) return;
1410
- if (await this.#checkSession()) return;
1411
1494
  if (this.#checkOffer()) return;
1495
+ this.#renderTemplate();
1496
+ if (await this.#checkSession()) return;
1412
1497
  this.#captureReturnUrl();
1413
1498
  this.#computeBillingCountries();
1414
1499
  if (await this.#fetchAndCacheOptions()) return;
1415
- this.#renderTemplate();
1500
+ this.#finishLoading();
1416
1501
  } catch {
1417
1502
  this.style.display = "none";
1503
+ this.querySelector(SEL_CONTAINER)?.remove();
1418
1504
  } finally {
1419
1505
  this.#rendering = false;
1420
1506
  }
@@ -1436,6 +1522,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1436
1522
  this.#sessionData = await this.#fetchSession();
1437
1523
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
1438
1524
  this.style.display = "none";
1525
+ this.querySelector(SEL_CONTAINER)?.remove();
1439
1526
  return true;
1440
1527
  }
1441
1528
  return false;
@@ -1471,6 +1558,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1471
1558
  this.#paymentOptions = await this.#fetchPaymentOptions();
1472
1559
  if (!this.#paymentOptions?.apple_pay) {
1473
1560
  this.style.display = "none";
1561
+ this.querySelector(SEL_CONTAINER)?.remove();
1474
1562
  return true;
1475
1563
  }
1476
1564
  return false;
@@ -1482,13 +1570,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1482
1570
  const template = document.createElement("template");
1483
1571
  template.innerHTML = apple_pay_button_template_default;
1484
1572
  this.appendChild(template.content.cloneNode(true));
1485
- this.#updateDisabledState();
1486
- trackExpressWalletImpression(this.#offer.sku_id, {
1487
- entryPoint: this.#entryPoint,
1488
- country: this.#country
1489
- });
1490
1573
  const button = this.querySelector(SEL_BUTTON);
1574
+ button.classList.add("wap-loading");
1575
+ button.setAttribute("disabled", "");
1576
+ button.setAttribute("aria-disabled", "true");
1577
+ button.setAttribute("aria-busy", "true");
1491
1578
  button.addEventListener("click", () => {
1579
+ if (button.classList.contains("wap-loading")) return;
1492
1580
  this.#openModal();
1493
1581
  });
1494
1582
  this.addEventListener("apple-pay-confirmed", (event) => {
@@ -1496,6 +1584,17 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1496
1584
  this.#initiateApplePay(skuId, country);
1497
1585
  });
1498
1586
  }
1587
+ #finishLoading() {
1588
+ const button = this.querySelector(SEL_BUTTON);
1589
+ if (button) {
1590
+ button.classList.remove("wap-loading");
1591
+ this.#updateDisabledState();
1592
+ trackExpressWalletImpression(this.#offer.sku_id, {
1593
+ entryPoint: this.#entryPoint,
1594
+ country: this.#country
1595
+ });
1596
+ }
1597
+ }
1499
1598
  // ─── Private helpers ────────────────────────────────────────────────────────
1500
1599
  #updateDisabledState() {
1501
1600
  const button = this.querySelector(SEL_BUTTON);
@@ -1503,6 +1602,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1503
1602
  if (this.#offer) {
1504
1603
  button.removeAttribute("disabled");
1505
1604
  button.removeAttribute("aria-disabled");
1605
+ button.removeAttribute("aria-busy");
1506
1606
  return;
1507
1607
  }
1508
1608
  button.setAttribute("disabled", "");
@@ -439,7 +439,91 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
439
439
  };
440
440
 
441
441
  // src/templates/apple-pay-button.template.html
442
- var apple_pay_button_template_default = '<style>\n /* Use CSS variables for layout so parent walls can easily override placement and sizing */\n teg-apple-pay-button {\n display: block;\n margin: var(--apple-pay-margin, 0);\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: var(--apple-pay-height, 2.75rem);\n background-color: #000;\n color: #fff;\n border: none;\n border-radius: var(--apple-pay-border-radius, 1.375rem);\n cursor: pointer;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-weight: 500;\n }\n\n teg-apple-pay-button .apple-pay-btn svg {\n flex-shrink: 0;\n display: block;\n }\n</style>\n\n<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">\n <button\n class="apple-pay-btn"\n type="button"\n aria-label="Pay with Apple Pay"\n data-analytics="paywall:apple-pay-checkout"\n >\n <svg width="51" height="22" aria-label="Apple Pay" role="img">\n <use href="#apple-pay-logo" />\n </svg>\n </button>\n</div>\n';
442
+ var apple_pay_button_template_default = `<style>
443
+ /* Use CSS variables for layout so parent walls can easily override placement and sizing */
444
+ teg-apple-pay-button {
445
+ display: block;
446
+ margin: var(--apple-pay-margin, 0);
447
+ width: 100%;
448
+ height: 100%;
449
+ }
450
+
451
+ teg-apple-pay-button .apple-pay-container {
452
+ display: flex;
453
+ flex-direction: column;
454
+ align-items: stretch;
455
+ width: 100%;
456
+ height: 100%;
457
+ }
458
+
459
+ teg-apple-pay-button .apple-pay-btn {
460
+ display: flex;
461
+ align-items: center;
462
+ justify-content: center;
463
+ gap: 0.375rem;
464
+ width: 100%;
465
+ min-width: 0;
466
+ height: 100%;
467
+ min-height: var(--apple-pay-height, 2.75rem);
468
+ background-color: #000;
469
+ color: #fff;
470
+ border: none;
471
+ border-radius: var(--apple-pay-border-radius, 1.375rem);
472
+ cursor: pointer;
473
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
474
+ font-size: 1.0625rem;
475
+ font-weight: 500;
476
+ }
477
+
478
+ teg-apple-pay-button .apple-pay-btn svg {
479
+ flex-shrink: 0;
480
+ display: block;
481
+ }
482
+
483
+ teg-apple-pay-button .apple-pay-btn.wap-loading {
484
+ position: relative;
485
+ cursor: default;
486
+ }
487
+
488
+ teg-apple-pay-button .apple-pay-btn.wap-loading svg {
489
+ visibility: hidden;
490
+ }
491
+
492
+ teg-apple-pay-button .apple-pay-btn.wap-loading::after {
493
+ content: '';
494
+ position: absolute;
495
+ left: 50%;
496
+ top: 50%;
497
+ margin-left: -0.625rem;
498
+ margin-top: -0.625rem;
499
+ width: 1.25rem;
500
+ height: 1.25rem;
501
+ border: 2px solid rgba(255, 255, 255, 0.2);
502
+ border-top-color: #fff;
503
+ border-radius: 50%;
504
+ animation: wap-button-spinner 0.8s linear infinite;
505
+ }
506
+
507
+ @keyframes wap-button-spinner {
508
+ to {
509
+ transform: rotate(360deg);
510
+ }
511
+ }
512
+ </style>
513
+
514
+ <div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
515
+ <button
516
+ class="apple-pay-btn"
517
+ type="button"
518
+ aria-label="Pay with Apple Pay"
519
+ data-analytics="paywall:apple-pay-checkout"
520
+ >
521
+ <svg width="51" height="22" aria-label="Apple Pay" role="img">
522
+ <use href="#apple-pay-logo" />
523
+ </svg>
524
+ </button>
525
+ </div>
526
+ `;
443
527
 
444
528
  // src/clients/payment-checkout/config.ts
445
529
  var runtimeConfig = null;
@@ -1402,14 +1486,16 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1402
1486
  async #run() {
1403
1487
  try {
1404
1488
  if (await this.#checkAvailability()) return;
1405
- if (await this.#checkSession()) return;
1406
1489
  if (this.#checkOffer()) return;
1490
+ this.#renderTemplate();
1491
+ if (await this.#checkSession()) return;
1407
1492
  this.#captureReturnUrl();
1408
1493
  this.#computeBillingCountries();
1409
1494
  if (await this.#fetchAndCacheOptions()) return;
1410
- this.#renderTemplate();
1495
+ this.#finishLoading();
1411
1496
  } catch {
1412
1497
  this.style.display = "none";
1498
+ this.querySelector(SEL_CONTAINER)?.remove();
1413
1499
  } finally {
1414
1500
  this.#rendering = false;
1415
1501
  }
@@ -1431,6 +1517,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1431
1517
  this.#sessionData = await this.#fetchSession();
1432
1518
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
1433
1519
  this.style.display = "none";
1520
+ this.querySelector(SEL_CONTAINER)?.remove();
1434
1521
  return true;
1435
1522
  }
1436
1523
  return false;
@@ -1466,6 +1553,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1466
1553
  this.#paymentOptions = await this.#fetchPaymentOptions();
1467
1554
  if (!this.#paymentOptions?.apple_pay) {
1468
1555
  this.style.display = "none";
1556
+ this.querySelector(SEL_CONTAINER)?.remove();
1469
1557
  return true;
1470
1558
  }
1471
1559
  return false;
@@ -1477,13 +1565,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1477
1565
  const template = document.createElement("template");
1478
1566
  template.innerHTML = apple_pay_button_template_default;
1479
1567
  this.appendChild(template.content.cloneNode(true));
1480
- this.#updateDisabledState();
1481
- trackExpressWalletImpression(this.#offer.sku_id, {
1482
- entryPoint: this.#entryPoint,
1483
- country: this.#country
1484
- });
1485
1568
  const button = this.querySelector(SEL_BUTTON);
1569
+ button.classList.add("wap-loading");
1570
+ button.setAttribute("disabled", "");
1571
+ button.setAttribute("aria-disabled", "true");
1572
+ button.setAttribute("aria-busy", "true");
1486
1573
  button.addEventListener("click", () => {
1574
+ if (button.classList.contains("wap-loading")) return;
1487
1575
  this.#openModal();
1488
1576
  });
1489
1577
  this.addEventListener("apple-pay-confirmed", (event) => {
@@ -1491,6 +1579,17 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1491
1579
  this.#initiateApplePay(skuId, country);
1492
1580
  });
1493
1581
  }
1582
+ #finishLoading() {
1583
+ const button = this.querySelector(SEL_BUTTON);
1584
+ if (button) {
1585
+ button.classList.remove("wap-loading");
1586
+ this.#updateDisabledState();
1587
+ trackExpressWalletImpression(this.#offer.sku_id, {
1588
+ entryPoint: this.#entryPoint,
1589
+ country: this.#country
1590
+ });
1591
+ }
1592
+ }
1494
1593
  // ─── Private helpers ────────────────────────────────────────────────────────
1495
1594
  #updateDisabledState() {
1496
1595
  const button = this.querySelector(SEL_BUTTON);
@@ -1498,6 +1597,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1498
1597
  if (this.#offer) {
1499
1598
  button.removeAttribute("disabled");
1500
1599
  button.removeAttribute("aria-disabled");
1600
+ button.removeAttribute("aria-busy");
1501
1601
  return;
1502
1602
  }
1503
1603
  button.setAttribute("disabled", "");
@@ -439,7 +439,91 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
439
439
  };
440
440
 
441
441
  // src/templates/apple-pay-button.template.html
442
- var apple_pay_button_template_default = '<style>\n /* Use CSS variables for layout so parent walls can easily override placement and sizing */\n teg-apple-pay-button {\n display: block;\n margin: var(--apple-pay-margin, 0);\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: var(--apple-pay-height, 2.75rem);\n background-color: #000;\n color: #fff;\n border: none;\n border-radius: var(--apple-pay-border-radius, 1.375rem);\n cursor: pointer;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-weight: 500;\n }\n\n teg-apple-pay-button .apple-pay-btn svg {\n flex-shrink: 0;\n display: block;\n }\n</style>\n\n<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">\n <button\n class="apple-pay-btn"\n type="button"\n aria-label="Pay with Apple Pay"\n data-analytics="paywall:apple-pay-checkout"\n >\n <svg width="51" height="22" aria-label="Apple Pay" role="img">\n <use href="#apple-pay-logo" />\n </svg>\n </button>\n</div>\n';
442
+ var apple_pay_button_template_default = `<style>
443
+ /* Use CSS variables for layout so parent walls can easily override placement and sizing */
444
+ teg-apple-pay-button {
445
+ display: block;
446
+ margin: var(--apple-pay-margin, 0);
447
+ width: 100%;
448
+ height: 100%;
449
+ }
450
+
451
+ teg-apple-pay-button .apple-pay-container {
452
+ display: flex;
453
+ flex-direction: column;
454
+ align-items: stretch;
455
+ width: 100%;
456
+ height: 100%;
457
+ }
458
+
459
+ teg-apple-pay-button .apple-pay-btn {
460
+ display: flex;
461
+ align-items: center;
462
+ justify-content: center;
463
+ gap: 0.375rem;
464
+ width: 100%;
465
+ min-width: 0;
466
+ height: 100%;
467
+ min-height: var(--apple-pay-height, 2.75rem);
468
+ background-color: #000;
469
+ color: #fff;
470
+ border: none;
471
+ border-radius: var(--apple-pay-border-radius, 1.375rem);
472
+ cursor: pointer;
473
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
474
+ font-size: 1.0625rem;
475
+ font-weight: 500;
476
+ }
477
+
478
+ teg-apple-pay-button .apple-pay-btn svg {
479
+ flex-shrink: 0;
480
+ display: block;
481
+ }
482
+
483
+ teg-apple-pay-button .apple-pay-btn.wap-loading {
484
+ position: relative;
485
+ cursor: default;
486
+ }
487
+
488
+ teg-apple-pay-button .apple-pay-btn.wap-loading svg {
489
+ visibility: hidden;
490
+ }
491
+
492
+ teg-apple-pay-button .apple-pay-btn.wap-loading::after {
493
+ content: '';
494
+ position: absolute;
495
+ left: 50%;
496
+ top: 50%;
497
+ margin-left: -0.625rem;
498
+ margin-top: -0.625rem;
499
+ width: 1.25rem;
500
+ height: 1.25rem;
501
+ border: 2px solid rgba(255, 255, 255, 0.2);
502
+ border-top-color: #fff;
503
+ border-radius: 50%;
504
+ animation: wap-button-spinner 0.8s linear infinite;
505
+ }
506
+
507
+ @keyframes wap-button-spinner {
508
+ to {
509
+ transform: rotate(360deg);
510
+ }
511
+ }
512
+ </style>
513
+
514
+ <div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
515
+ <button
516
+ class="apple-pay-btn"
517
+ type="button"
518
+ aria-label="Pay with Apple Pay"
519
+ data-analytics="paywall:apple-pay-checkout"
520
+ >
521
+ <svg width="51" height="22" aria-label="Apple Pay" role="img">
522
+ <use href="#apple-pay-logo" />
523
+ </svg>
524
+ </button>
525
+ </div>
526
+ `;
443
527
 
444
528
  // src/clients/payment-checkout/config.ts
445
529
  var runtimeConfig = null;
@@ -1410,14 +1494,16 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1410
1494
  async #run() {
1411
1495
  try {
1412
1496
  if (await this.#checkAvailability()) return;
1413
- if (await this.#checkSession()) return;
1414
1497
  if (this.#checkOffer()) return;
1498
+ this.#renderTemplate();
1499
+ if (await this.#checkSession()) return;
1415
1500
  this.#captureReturnUrl();
1416
1501
  this.#computeBillingCountries();
1417
1502
  if (await this.#fetchAndCacheOptions()) return;
1418
- this.#renderTemplate();
1503
+ this.#finishLoading();
1419
1504
  } catch {
1420
1505
  this.style.display = "none";
1506
+ this.querySelector(SEL_CONTAINER)?.remove();
1421
1507
  } finally {
1422
1508
  this.#rendering = false;
1423
1509
  }
@@ -1439,6 +1525,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1439
1525
  this.#sessionData = await this.#fetchSession();
1440
1526
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
1441
1527
  this.style.display = "none";
1528
+ this.querySelector(SEL_CONTAINER)?.remove();
1442
1529
  return true;
1443
1530
  }
1444
1531
  return false;
@@ -1474,6 +1561,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1474
1561
  this.#paymentOptions = await this.#fetchPaymentOptions();
1475
1562
  if (!this.#paymentOptions?.apple_pay) {
1476
1563
  this.style.display = "none";
1564
+ this.querySelector(SEL_CONTAINER)?.remove();
1477
1565
  return true;
1478
1566
  }
1479
1567
  return false;
@@ -1485,13 +1573,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1485
1573
  const template = document.createElement("template");
1486
1574
  template.innerHTML = apple_pay_button_template_default;
1487
1575
  this.appendChild(template.content.cloneNode(true));
1488
- this.#updateDisabledState();
1489
- trackExpressWalletImpression(this.#offer.sku_id, {
1490
- entryPoint: this.#entryPoint,
1491
- country: this.#country
1492
- });
1493
1576
  const button = this.querySelector(SEL_BUTTON);
1577
+ button.classList.add("wap-loading");
1578
+ button.setAttribute("disabled", "");
1579
+ button.setAttribute("aria-disabled", "true");
1580
+ button.setAttribute("aria-busy", "true");
1494
1581
  button.addEventListener("click", () => {
1582
+ if (button.classList.contains("wap-loading")) return;
1495
1583
  this.#openModal();
1496
1584
  });
1497
1585
  this.addEventListener("apple-pay-confirmed", (event) => {
@@ -1499,6 +1587,17 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1499
1587
  this.#initiateApplePay(skuId, country);
1500
1588
  });
1501
1589
  }
1590
+ #finishLoading() {
1591
+ const button = this.querySelector(SEL_BUTTON);
1592
+ if (button) {
1593
+ button.classList.remove("wap-loading");
1594
+ this.#updateDisabledState();
1595
+ trackExpressWalletImpression(this.#offer.sku_id, {
1596
+ entryPoint: this.#entryPoint,
1597
+ country: this.#country
1598
+ });
1599
+ }
1600
+ }
1502
1601
  // ─── Private helpers ────────────────────────────────────────────────────────
1503
1602
  #updateDisabledState() {
1504
1603
  const button = this.querySelector(SEL_BUTTON);
@@ -1506,6 +1605,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1506
1605
  if (this.#offer) {
1507
1606
  button.removeAttribute("disabled");
1508
1607
  button.removeAttribute("aria-disabled");
1608
+ button.removeAttribute("aria-busy");
1509
1609
  return;
1510
1610
  }
1511
1611
  button.setAttribute("disabled", "");
@@ -439,7 +439,91 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
439
439
  };
440
440
 
441
441
  // src/templates/apple-pay-button.template.html
442
- var apple_pay_button_template_default = '<style>\n /* Use CSS variables for layout so parent walls can easily override placement and sizing */\n teg-apple-pay-button {\n display: block;\n margin: var(--apple-pay-margin, 0);\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: var(--apple-pay-height, 2.75rem);\n background-color: #000;\n color: #fff;\n border: none;\n border-radius: var(--apple-pay-border-radius, 1.375rem);\n cursor: pointer;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-weight: 500;\n }\n\n teg-apple-pay-button .apple-pay-btn svg {\n flex-shrink: 0;\n display: block;\n }\n</style>\n\n<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">\n <button\n class="apple-pay-btn"\n type="button"\n aria-label="Pay with Apple Pay"\n data-analytics="paywall:apple-pay-checkout"\n >\n <svg width="51" height="22" aria-label="Apple Pay" role="img">\n <use href="#apple-pay-logo" />\n </svg>\n </button>\n</div>\n';
442
+ var apple_pay_button_template_default = `<style>
443
+ /* Use CSS variables for layout so parent walls can easily override placement and sizing */
444
+ teg-apple-pay-button {
445
+ display: block;
446
+ margin: var(--apple-pay-margin, 0);
447
+ width: 100%;
448
+ height: 100%;
449
+ }
450
+
451
+ teg-apple-pay-button .apple-pay-container {
452
+ display: flex;
453
+ flex-direction: column;
454
+ align-items: stretch;
455
+ width: 100%;
456
+ height: 100%;
457
+ }
458
+
459
+ teg-apple-pay-button .apple-pay-btn {
460
+ display: flex;
461
+ align-items: center;
462
+ justify-content: center;
463
+ gap: 0.375rem;
464
+ width: 100%;
465
+ min-width: 0;
466
+ height: 100%;
467
+ min-height: var(--apple-pay-height, 2.75rem);
468
+ background-color: #000;
469
+ color: #fff;
470
+ border: none;
471
+ border-radius: var(--apple-pay-border-radius, 1.375rem);
472
+ cursor: pointer;
473
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
474
+ font-size: 1.0625rem;
475
+ font-weight: 500;
476
+ }
477
+
478
+ teg-apple-pay-button .apple-pay-btn svg {
479
+ flex-shrink: 0;
480
+ display: block;
481
+ }
482
+
483
+ teg-apple-pay-button .apple-pay-btn.wap-loading {
484
+ position: relative;
485
+ cursor: default;
486
+ }
487
+
488
+ teg-apple-pay-button .apple-pay-btn.wap-loading svg {
489
+ visibility: hidden;
490
+ }
491
+
492
+ teg-apple-pay-button .apple-pay-btn.wap-loading::after {
493
+ content: '';
494
+ position: absolute;
495
+ left: 50%;
496
+ top: 50%;
497
+ margin-left: -0.625rem;
498
+ margin-top: -0.625rem;
499
+ width: 1.25rem;
500
+ height: 1.25rem;
501
+ border: 2px solid rgba(255, 255, 255, 0.2);
502
+ border-top-color: #fff;
503
+ border-radius: 50%;
504
+ animation: wap-button-spinner 0.8s linear infinite;
505
+ }
506
+
507
+ @keyframes wap-button-spinner {
508
+ to {
509
+ transform: rotate(360deg);
510
+ }
511
+ }
512
+ </style>
513
+
514
+ <div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
515
+ <button
516
+ class="apple-pay-btn"
517
+ type="button"
518
+ aria-label="Pay with Apple Pay"
519
+ data-analytics="paywall:apple-pay-checkout"
520
+ >
521
+ <svg width="51" height="22" aria-label="Apple Pay" role="img">
522
+ <use href="#apple-pay-logo" />
523
+ </svg>
524
+ </button>
525
+ </div>
526
+ `;
443
527
 
444
528
  // src/clients/payment-checkout/config.ts
445
529
  var runtimeConfig = null;
@@ -1402,14 +1486,16 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1402
1486
  async #run() {
1403
1487
  try {
1404
1488
  if (await this.#checkAvailability()) return;
1405
- if (await this.#checkSession()) return;
1406
1489
  if (this.#checkOffer()) return;
1490
+ this.#renderTemplate();
1491
+ if (await this.#checkSession()) return;
1407
1492
  this.#captureReturnUrl();
1408
1493
  this.#computeBillingCountries();
1409
1494
  if (await this.#fetchAndCacheOptions()) return;
1410
- this.#renderTemplate();
1495
+ this.#finishLoading();
1411
1496
  } catch {
1412
1497
  this.style.display = "none";
1498
+ this.querySelector(SEL_CONTAINER)?.remove();
1413
1499
  } finally {
1414
1500
  this.#rendering = false;
1415
1501
  }
@@ -1431,6 +1517,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1431
1517
  this.#sessionData = await this.#fetchSession();
1432
1518
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
1433
1519
  this.style.display = "none";
1520
+ this.querySelector(SEL_CONTAINER)?.remove();
1434
1521
  return true;
1435
1522
  }
1436
1523
  return false;
@@ -1466,6 +1553,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1466
1553
  this.#paymentOptions = await this.#fetchPaymentOptions();
1467
1554
  if (!this.#paymentOptions?.apple_pay) {
1468
1555
  this.style.display = "none";
1556
+ this.querySelector(SEL_CONTAINER)?.remove();
1469
1557
  return true;
1470
1558
  }
1471
1559
  return false;
@@ -1477,13 +1565,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1477
1565
  const template = document.createElement("template");
1478
1566
  template.innerHTML = apple_pay_button_template_default;
1479
1567
  this.appendChild(template.content.cloneNode(true));
1480
- this.#updateDisabledState();
1481
- trackExpressWalletImpression(this.#offer.sku_id, {
1482
- entryPoint: this.#entryPoint,
1483
- country: this.#country
1484
- });
1485
1568
  const button = this.querySelector(SEL_BUTTON);
1569
+ button.classList.add("wap-loading");
1570
+ button.setAttribute("disabled", "");
1571
+ button.setAttribute("aria-disabled", "true");
1572
+ button.setAttribute("aria-busy", "true");
1486
1573
  button.addEventListener("click", () => {
1574
+ if (button.classList.contains("wap-loading")) return;
1487
1575
  this.#openModal();
1488
1576
  });
1489
1577
  this.addEventListener("apple-pay-confirmed", (event) => {
@@ -1491,6 +1579,17 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1491
1579
  this.#initiateApplePay(skuId, country);
1492
1580
  });
1493
1581
  }
1582
+ #finishLoading() {
1583
+ const button = this.querySelector(SEL_BUTTON);
1584
+ if (button) {
1585
+ button.classList.remove("wap-loading");
1586
+ this.#updateDisabledState();
1587
+ trackExpressWalletImpression(this.#offer.sku_id, {
1588
+ entryPoint: this.#entryPoint,
1589
+ country: this.#country
1590
+ });
1591
+ }
1592
+ }
1494
1593
  // ─── Private helpers ────────────────────────────────────────────────────────
1495
1594
  #updateDisabledState() {
1496
1595
  const button = this.querySelector(SEL_BUTTON);
@@ -1498,6 +1597,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1498
1597
  if (this.#offer) {
1499
1598
  button.removeAttribute("disabled");
1500
1599
  button.removeAttribute("aria-disabled");
1600
+ button.removeAttribute("aria-busy");
1501
1601
  return;
1502
1602
  }
1503
1603
  button.setAttribute("disabled", "");
package/dist/src/index.js CHANGED
@@ -439,7 +439,91 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
439
439
  };
440
440
 
441
441
  // src/templates/apple-pay-button.template.html
442
- var apple_pay_button_template_default = '<style>\n /* Use CSS variables for layout so parent walls can easily override placement and sizing */\n teg-apple-pay-button {\n display: block;\n margin: var(--apple-pay-margin, 0);\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n }\n\n teg-apple-pay-button .apple-pay-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: var(--apple-pay-height, 2.75rem);\n background-color: #000;\n color: #fff;\n border: none;\n border-radius: var(--apple-pay-border-radius, 1.375rem);\n cursor: pointer;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-weight: 500;\n }\n\n teg-apple-pay-button .apple-pay-btn svg {\n flex-shrink: 0;\n display: block;\n }\n</style>\n\n<div class="apple-pay-container" aria-label="Express checkout with Apple Pay">\n <button\n class="apple-pay-btn"\n type="button"\n aria-label="Pay with Apple Pay"\n data-analytics="paywall:apple-pay-checkout"\n >\n <svg width="51" height="22" aria-label="Apple Pay" role="img">\n <use href="#apple-pay-logo" />\n </svg>\n </button>\n</div>\n';
442
+ var apple_pay_button_template_default = `<style>
443
+ /* Use CSS variables for layout so parent walls can easily override placement and sizing */
444
+ teg-apple-pay-button {
445
+ display: block;
446
+ margin: var(--apple-pay-margin, 0);
447
+ width: 100%;
448
+ height: 100%;
449
+ }
450
+
451
+ teg-apple-pay-button .apple-pay-container {
452
+ display: flex;
453
+ flex-direction: column;
454
+ align-items: stretch;
455
+ width: 100%;
456
+ height: 100%;
457
+ }
458
+
459
+ teg-apple-pay-button .apple-pay-btn {
460
+ display: flex;
461
+ align-items: center;
462
+ justify-content: center;
463
+ gap: 0.375rem;
464
+ width: 100%;
465
+ min-width: 0;
466
+ height: 100%;
467
+ min-height: var(--apple-pay-height, 2.75rem);
468
+ background-color: #000;
469
+ color: #fff;
470
+ border: none;
471
+ border-radius: var(--apple-pay-border-radius, 1.375rem);
472
+ cursor: pointer;
473
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
474
+ font-size: 1.0625rem;
475
+ font-weight: 500;
476
+ }
477
+
478
+ teg-apple-pay-button .apple-pay-btn svg {
479
+ flex-shrink: 0;
480
+ display: block;
481
+ }
482
+
483
+ teg-apple-pay-button .apple-pay-btn.wap-loading {
484
+ position: relative;
485
+ cursor: default;
486
+ }
487
+
488
+ teg-apple-pay-button .apple-pay-btn.wap-loading svg {
489
+ visibility: hidden;
490
+ }
491
+
492
+ teg-apple-pay-button .apple-pay-btn.wap-loading::after {
493
+ content: '';
494
+ position: absolute;
495
+ left: 50%;
496
+ top: 50%;
497
+ margin-left: -0.625rem;
498
+ margin-top: -0.625rem;
499
+ width: 1.25rem;
500
+ height: 1.25rem;
501
+ border: 2px solid rgba(255, 255, 255, 0.2);
502
+ border-top-color: #fff;
503
+ border-radius: 50%;
504
+ animation: wap-button-spinner 0.8s linear infinite;
505
+ }
506
+
507
+ @keyframes wap-button-spinner {
508
+ to {
509
+ transform: rotate(360deg);
510
+ }
511
+ }
512
+ </style>
513
+
514
+ <div class="apple-pay-container" aria-label="Express checkout with Apple Pay">
515
+ <button
516
+ class="apple-pay-btn"
517
+ type="button"
518
+ aria-label="Pay with Apple Pay"
519
+ data-analytics="paywall:apple-pay-checkout"
520
+ >
521
+ <svg width="51" height="22" aria-label="Apple Pay" role="img">
522
+ <use href="#apple-pay-logo" />
523
+ </svg>
524
+ </button>
525
+ </div>
526
+ `;
443
527
 
444
528
  // src/clients/payment-checkout/config.ts
445
529
  var runtimeConfig = null;
@@ -1407,14 +1491,16 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1407
1491
  async #run() {
1408
1492
  try {
1409
1493
  if (await this.#checkAvailability()) return;
1410
- if (await this.#checkSession()) return;
1411
1494
  if (this.#checkOffer()) return;
1495
+ this.#renderTemplate();
1496
+ if (await this.#checkSession()) return;
1412
1497
  this.#captureReturnUrl();
1413
1498
  this.#computeBillingCountries();
1414
1499
  if (await this.#fetchAndCacheOptions()) return;
1415
- this.#renderTemplate();
1500
+ this.#finishLoading();
1416
1501
  } catch {
1417
1502
  this.style.display = "none";
1503
+ this.querySelector(SEL_CONTAINER)?.remove();
1418
1504
  } finally {
1419
1505
  this.#rendering = false;
1420
1506
  }
@@ -1436,6 +1522,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1436
1522
  this.#sessionData = await this.#fetchSession();
1437
1523
  if (this.#sessionData?.loggedIn && (this.#sessionData.userType === "active-subscription" || this.#sessionData.userType === "b2b-user")) {
1438
1524
  this.style.display = "none";
1525
+ this.querySelector(SEL_CONTAINER)?.remove();
1439
1526
  return true;
1440
1527
  }
1441
1528
  return false;
@@ -1471,6 +1558,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1471
1558
  this.#paymentOptions = await this.#fetchPaymentOptions();
1472
1559
  if (!this.#paymentOptions?.apple_pay) {
1473
1560
  this.style.display = "none";
1561
+ this.querySelector(SEL_CONTAINER)?.remove();
1474
1562
  return true;
1475
1563
  }
1476
1564
  return false;
@@ -1482,13 +1570,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1482
1570
  const template = document.createElement("template");
1483
1571
  template.innerHTML = apple_pay_button_template_default;
1484
1572
  this.appendChild(template.content.cloneNode(true));
1485
- this.#updateDisabledState();
1486
- trackExpressWalletImpression(this.#offer.sku_id, {
1487
- entryPoint: this.#entryPoint,
1488
- country: this.#country
1489
- });
1490
1573
  const button = this.querySelector(SEL_BUTTON);
1574
+ button.classList.add("wap-loading");
1575
+ button.setAttribute("disabled", "");
1576
+ button.setAttribute("aria-disabled", "true");
1577
+ button.setAttribute("aria-busy", "true");
1491
1578
  button.addEventListener("click", () => {
1579
+ if (button.classList.contains("wap-loading")) return;
1492
1580
  this.#openModal();
1493
1581
  });
1494
1582
  this.addEventListener("apple-pay-confirmed", (event) => {
@@ -1496,6 +1584,17 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1496
1584
  this.#initiateApplePay(skuId, country);
1497
1585
  });
1498
1586
  }
1587
+ #finishLoading() {
1588
+ const button = this.querySelector(SEL_BUTTON);
1589
+ if (button) {
1590
+ button.classList.remove("wap-loading");
1591
+ this.#updateDisabledState();
1592
+ trackExpressWalletImpression(this.#offer.sku_id, {
1593
+ entryPoint: this.#entryPoint,
1594
+ country: this.#country
1595
+ });
1596
+ }
1597
+ }
1499
1598
  // ─── Private helpers ────────────────────────────────────────────────────────
1500
1599
  #updateDisabledState() {
1501
1600
  const button = this.querySelector(SEL_BUTTON);
@@ -1503,6 +1602,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1503
1602
  if (this.#offer) {
1504
1603
  button.removeAttribute("disabled");
1505
1604
  button.removeAttribute("aria-disabled");
1605
+ button.removeAttribute("aria-busy");
1506
1606
  return;
1507
1607
  }
1508
1608
  button.setAttribute("disabled", "");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@economist/web-apple-pay",
3
3
  "description": "Web component package for Apple Pay checkout UI",
4
- "version": "1.6.1",
4
+ "version": "1.7.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",