@economist/web-apple-pay 1.7.3 → 1.7.5

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
@@ -76,7 +76,514 @@ function ensureApplePayLogoSymbol() {
76
76
  }
77
77
 
78
78
  // src/templates/apple-pay-modal.template.html
79
- var apple_pay_modal_template_default = '<style>\n .apm-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 97;\n background: rgba(13, 13, 13, 0.7);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--wall-gutter, 2rem);\n box-sizing: border-box;\n }\n\n .apm {\n position: relative;\n background: #fff;\n border-radius: 0.5rem 0.5rem 0 0;\n border: 0.0625rem solid #d9d9d9;\n padding: var(--mb-spacing-lg, 1.5rem);\n width: 25rem;\n max-width: 25rem;\n box-sizing: border-box;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n box-shadow: 0 0.25rem 1rem 0 rgba(13, 13, 13, 0.15);\n }\n\n .apm__close {\n position: absolute;\n top: 1.5rem;\n right: 1.3125rem;\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .apm__close:focus {\n outline: solid 0.125rem var(--focus-border-color, #121212);\n border-radius: 0.25rem;\n }\n\n .apm__offer-name {\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-title-3-size, 1.25rem);\n font-weight: 500;\n color: var(--mb-colour-greyscale-london-5, #0d0d0d);\n line-height: var(--mb-typestyle-title-3-leading, 1.75rem);\n font-style: normal;\n margin: 0 1.5rem 0.5rem 0;\n }\n\n .apm__due-today {\n color: #1a1a1a;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n font-style: normal;\n font-weight: 400;\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n margin: 0 0 0.75rem 0;\n }\n\n .apm__rule {\n border: none;\n border-top: 0.0625rem solid #d9d9d9;\n margin: 0 0 1rem 0;\n }\n\n .apm__terms {\n color: #1a1a1a;\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n font-style: normal;\n font-weight: 400;\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n margin: 0 0 1rem 0;\n }\n\n .apm__terms-bullets {\n list-style: disc outside;\n padding-left: 1.25rem;\n margin: 0 0 0.75rem 0;\n }\n\n .apm__terms-bullets li {\n margin-bottom: 0.375rem;\n }\n\n .apm__terms-legal {\n margin: 0;\n }\n\n .apm__passive-terms {\n font-family: var(--wall-type-system-sans);\n font-size: 0.9375rem;\n color: #0d0d0d;\n line-height: 1.4;\n margin: 0 0 8px 0;\n }\n\n .apm__passive-terms a {\n color: #1a1a1a;\n font-weight: 700;\n text-decoration: underline;\n }\n\n .apm__checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: var(--mb-spacing-sm, 0.5rem);\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: var(--mb-typestyle-label-2-size, 0.9375rem);\n color: var(--mb-colour-greyscale-london-20, #1a1a1a);\n line-height: var(--mb-typestyle-label-2-leading, 1.25rem);\n cursor: pointer;\n margin: 0 0 1.5rem 0;\n }\n\n .apm__checkbox-label--error {\n margin-bottom: 0.25rem;\n }\n\n .apm__checkbox-wrapper {\n position: relative;\n flex-shrink: 0;\n width: 1.25rem;\n height: 1.25rem;\n margin-top: 0.0625rem;\n }\n\n .apm__checkbox-input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n margin: 0;\n z-index: 1;\n }\n\n .apm__checkbox-custom {\n position: absolute;\n top: 0;\n left: 0;\n width: 1.25rem;\n height: 1.25rem;\n pointer-events: none;\n }\n\n .apm__checkbox-custom svg {\n display: none;\n width: 1.25rem;\n height: 1.25rem;\n }\n\n .apm__checkbox-input:not(:checked) ~ .apm__checkbox-custom .svg-unchecked {\n display: block;\n }\n\n .apm__checkbox-input:checked ~ .apm__checkbox-custom .svg-checked {\n display: block;\n }\n\n .apm__checkbox-label--error\n .apm__checkbox-input:not(:checked)\n ~ .apm__checkbox-custom\n .svg-unchecked {\n display: none;\n }\n\n .apm__checkbox-label--error\n .apm__checkbox-input:not(:checked)\n ~ .apm__checkbox-custom\n .svg-error {\n display: block;\n }\n\n .apm__checkbox-input:focus-visible ~ .apm__checkbox-custom {\n outline: solid 0.125rem #c91d42;\n outline-offset: 0.125rem;\n border-radius: 0.25rem;\n }\n\n .apm__checkbox-label a {\n color: #1a1a1a;\n font-weight: 700;\n text-decoration: underline;\n }\n\n .apm__error {\n display: none;\n align-items: center;\n gap: 0.75rem;\n color: var(--mb-colour-greyscale-london-5, #0d0d0d);\n font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));\n font-size: 1.0625rem;\n font-style: normal;\n font-weight: 500;\n line-height: 1.5rem;\n margin-bottom: 1rem;\n }\n\n .apm__error--visible {\n display: flex;\n }\n\n .apm__cta {\n display: flex;\n width: 100%;\n height: 2.75rem;\n padding: 0.375rem 1rem;\n justify-content: center;\n align-items: center;\n gap: 0.375rem;\n border-radius: 0.25rem;\n background: #000;\n border: none;\n cursor: pointer;\n color: #fff;\n text-align: center;\n font-family: var(\n --mb-typeface-sans,\n var(--wall-type-system-sans, system-ui, sans-serif)\n );\n font-size: 1.25rem;\n font-style: normal;\n font-weight: 500;\n line-height: normal;\n }\n\n .apm__cta svg {\n flex-shrink: 0;\n display: block;\n }\n\n @media (min-width: 22.5rem) and (max-width: 37.5rem) {\n .apm {\n width: 24.375rem;\n max-width: 24.375rem;\n }\n }\n\n @media (min-width: 37.5625rem) {\n .apm {\n border-radius: 0.5rem;\n }\n }\n\n @media (max-width: 22.4375rem) {\n .apm {\n width: 20rem;\n max-width: 20rem;\n }\n }\n\n @media (max-width: 26.1875rem) {\n .apm__cta {\n font-size: 1.125rem;\n }\n }\n</style>\n\n<div class="apm-overlay" id="apple-pay-modal-overlay">\n <div\n class="apm"\n role="dialog"\n aria-modal="true"\n aria-labelledby="apple-pay-modal-offer-name"\n id="apple-pay-modal"\n tabindex="-1"\n >\n <button class="apm__close" id="apple-pay-modal-close" aria-label="Close">\n <svg\n aria-hidden="true"\n xmlns="http://www.w3.org/2000/svg"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n >\n <g clip-path="url(#clip0_15712_93054)">\n <rect width="24" height="24" fill="white" fill-opacity="0.01" />\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M0 0H24V24H0V0Z"\n fill="white"\n fill-opacity="0.01"\n />\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M18.75 6.60964L17.3904 5.25L12 10.6404L6.60964 5.25L5.25 6.60964L10.6404 12L5.25 17.3904L6.60964 18.75L12 13.3596L17.3904 18.75L18.75 17.3904L13.3596 12L18.75 6.60964Z"\n fill="#333333"\n />\n </g>\n <defs>\n <clipPath id="clip0_15712_93054">\n <rect width="24" height="24" fill="white" />\n </clipPath>\n </defs>\n </svg>\n </button>\n <p class="apm__offer-name" id="apple-pay-modal-offer-name"></p>\n <p class="apm__due-today" id="apple-pay-modal-due-today"></p>\n <hr class="apm__rule" />\n <div class="apm__terms" id="apple-pay-modal-terms"></div>\n <p class="apm__passive-terms" id="apple-pay-modal-passive-terms"></p>\n <label\n class="apm__checkbox-label"\n id="apple-pay-modal-checkbox-label"\n for="apple-pay-modal-checkbox"\n >\n <div class="apm__checkbox-wrapper">\n <input\n class="apm__checkbox-input"\n type="checkbox"\n id="apple-pay-modal-checkbox"\n />\n <span class="apm__checkbox-custom">\n <svg\n aria-hidden="true"\n class="svg-unchecked"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"\n fill="white"\n stroke="#595959"\n />\n </svg>\n <svg\n aria-hidden="true"\n class="svg-checked"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <g clip-path="url(#clip0_20014_9555)">\n <path\n d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"\n fill="#333333"\n />\n <path\n d="M10.2857 17L6 12.6814L7.20857 11.4635L10.2857 14.5557L16.7914 8L18 9.22649L10.2857 17Z"\n fill="white"\n />\n </g>\n <defs>\n <clipPath id="clip0_20014_9555">\n <path\n d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"\n fill="white"\n />\n </clipPath>\n </defs>\n </svg>\n <svg\n aria-hidden="true"\n class="svg-error"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"\n fill="white"\n stroke="#C91D42"\n stroke-width="2"\n />\n </svg>\n </span>\n </div>\n <span id="apple-pay-modal-checkbox-text"></span>\n </label>\n <div class="apm__error" id="apple-pay-modal-error" role="alert">\n <svg\n aria-hidden="true"\n width="20"\n height="20"\n viewBox="0 0 20 20"\n fill="none"\n xmlns="http://www.w3.org/2000/svg"\n >\n <path\n fill-rule="evenodd"\n clip-rule="evenodd"\n d="M10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2ZM0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10ZM11 13C11 13.5523 10.5523 14 10 14C9.44772 14 9 13.5523 9 13C9 12.4477 9.44772 12 10 12C10.5523 12 11 12.4477 11 13ZM10 6C10.5523 6 11 6.44772 11 7V10C11 10.5523 10.5523 11 10 11C9.44772 11 9 10.5523 9 10V7C9 6.44772 9.44772 6 10 6Z"\n fill="#C91D42"\n />\n </svg>\n Please accept the terms to continue\n </div>\n <button class="apm__cta" id="apple-pay-modal-cta">\n Continue with\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</div>\n\n';
79
+ var apple_pay_modal_template_default = `<style>
80
+ .apm-overlay {
81
+ position: fixed;
82
+ top: 0;
83
+ left: 0;
84
+ width: 100%;
85
+ height: 100%;
86
+ z-index: 97;
87
+ background: rgba(13, 13, 13, 0.7);
88
+ display: flex;
89
+ align-items: center;
90
+ justify-content: center;
91
+ padding: var(--wall-gutter, 2rem);
92
+ box-sizing: border-box;
93
+ }
94
+
95
+ .apm {
96
+ position: relative;
97
+ background: #fff;
98
+ border-radius: 0.5rem 0.5rem 0 0;
99
+ border: 0.0625rem solid #d9d9d9;
100
+ padding: var(--mb-spacing-lg, 1.5rem);
101
+ width: 25rem;
102
+ max-width: 25rem;
103
+ box-sizing: border-box;
104
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
105
+ box-shadow: 0 0.25rem 1rem 0 rgba(13, 13, 13, 0.15);
106
+ }
107
+
108
+ .apm__close {
109
+ position: absolute;
110
+ top: 1.5rem;
111
+ right: 1.3125rem;
112
+ background: none;
113
+ border: none;
114
+ cursor: pointer;
115
+ padding: 0;
116
+ display: flex;
117
+ align-items: center;
118
+ justify-content: center;
119
+ }
120
+
121
+ .apm__close:focus {
122
+ outline: solid 0.125rem var(--focus-border-color, #121212);
123
+ border-radius: 0.25rem;
124
+ }
125
+
126
+ .apm__offer-name {
127
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
128
+ font-size: var(--mb-typestyle-title-3-size, 1.25rem);
129
+ font-weight: 500;
130
+ color: var(--mb-colour-greyscale-london-5, #0d0d0d);
131
+ line-height: var(--mb-typestyle-title-3-leading, 1.75rem);
132
+ font-style: normal;
133
+ margin: 0 1.5rem 0.5rem 0;
134
+ }
135
+
136
+ .apm__due-today {
137
+ color: #1a1a1a;
138
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
139
+ font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
140
+ font-style: normal;
141
+ font-weight: 400;
142
+ line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
143
+ margin: 0 0 0.75rem 0;
144
+ }
145
+
146
+ .apm__rule {
147
+ border: none;
148
+ border-top: 0.0625rem solid #d9d9d9;
149
+ margin: 0 0 1rem 0;
150
+ }
151
+
152
+ .apm__terms {
153
+ color: #1a1a1a;
154
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
155
+ font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
156
+ font-style: normal;
157
+ font-weight: 400;
158
+ line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
159
+ margin: 0 0 1rem 0;
160
+ }
161
+
162
+ .apm__terms-bullets {
163
+ list-style: disc outside;
164
+ padding-left: 1.25rem;
165
+ margin: 0 0 0.75rem 0;
166
+ }
167
+
168
+ .apm__terms-bullets li {
169
+ margin-bottom: 0.375rem;
170
+ }
171
+
172
+ .apm__terms-legal {
173
+ margin: 0;
174
+ }
175
+
176
+ .apm__passive-terms {
177
+ font-family: var(--wall-type-system-sans);
178
+ font-size: 0.9375rem;
179
+ color: #0d0d0d;
180
+ line-height: 1.4;
181
+ margin: 0 0 8px 0;
182
+ }
183
+
184
+ .apm__passive-terms a {
185
+ color: #1a1a1a;
186
+ font-weight: 700;
187
+ text-decoration: underline;
188
+ }
189
+
190
+ .apm__checkbox-label {
191
+ display: flex;
192
+ align-items: flex-start;
193
+ gap: var(--mb-spacing-sm, 0.5rem);
194
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
195
+ font-size: var(--mb-typestyle-label-2-size, 0.9375rem);
196
+ color: var(--mb-colour-greyscale-london-20, #1a1a1a);
197
+ line-height: var(--mb-typestyle-label-2-leading, 1.25rem);
198
+ cursor: pointer;
199
+ margin: 0 0 1.5rem 0;
200
+ }
201
+
202
+ .apm__checkbox-label--error {
203
+ margin-bottom: 0.25rem;
204
+ }
205
+
206
+ .apm__checkbox-wrapper {
207
+ position: relative;
208
+ flex-shrink: 0;
209
+ width: 1.25rem;
210
+ height: 1.25rem;
211
+ margin-top: 0.0625rem;
212
+ }
213
+
214
+ .apm__checkbox-input {
215
+ position: absolute;
216
+ opacity: 0;
217
+ width: 100%;
218
+ height: 100%;
219
+ cursor: pointer;
220
+ margin: 0;
221
+ z-index: 1;
222
+ }
223
+
224
+ .apm__checkbox-custom {
225
+ position: absolute;
226
+ top: 0;
227
+ left: 0;
228
+ width: 1.25rem;
229
+ height: 1.25rem;
230
+ pointer-events: none;
231
+ }
232
+
233
+ .apm__checkbox-custom svg {
234
+ display: none;
235
+ width: 1.25rem;
236
+ height: 1.25rem;
237
+ }
238
+
239
+ .apm__checkbox-input:not(:checked) ~ .apm__checkbox-custom .svg-unchecked {
240
+ display: block;
241
+ }
242
+
243
+ .apm__checkbox-input:checked ~ .apm__checkbox-custom .svg-checked {
244
+ display: block;
245
+ }
246
+
247
+ .apm__checkbox-label--error
248
+ .apm__checkbox-input:not(:checked)
249
+ ~ .apm__checkbox-custom
250
+ .svg-unchecked {
251
+ display: none;
252
+ }
253
+
254
+ .apm__checkbox-label--error
255
+ .apm__checkbox-input:not(:checked)
256
+ ~ .apm__checkbox-custom
257
+ .svg-error {
258
+ display: block;
259
+ }
260
+
261
+ .apm__checkbox-input:focus-visible ~ .apm__checkbox-custom {
262
+ outline: solid 0.125rem #c91d42;
263
+ outline-offset: 0.125rem;
264
+ border-radius: 0.25rem;
265
+ }
266
+
267
+ .apm__checkbox-label a {
268
+ color: #1a1a1a;
269
+ font-weight: 700;
270
+ text-decoration: underline;
271
+ }
272
+
273
+ .apm__error {
274
+ display: none;
275
+ align-items: center;
276
+ gap: 0.75rem;
277
+ color: var(--mb-colour-greyscale-london-5, #0d0d0d);
278
+ font-family: var(--mb-typeface-sans, var(--wall-type-system-sans));
279
+ font-size: 1.0625rem;
280
+ font-style: normal;
281
+ font-weight: 500;
282
+ line-height: 1.5rem;
283
+ margin-bottom: 1rem;
284
+ }
285
+
286
+ .apm__error--visible {
287
+ display: flex;
288
+ }
289
+
290
+ .apm__cta {
291
+ display: flex;
292
+ width: 100%;
293
+ height: 2.75rem;
294
+ padding: 0.375rem 1rem;
295
+ justify-content: center;
296
+ align-items: center;
297
+ gap: 0.375rem;
298
+ border-radius: 0.25rem;
299
+ background: #000;
300
+ border: none;
301
+ cursor: pointer;
302
+ color: #fff;
303
+ text-align: center;
304
+ font-family: var(
305
+ --mb-typeface-sans,
306
+ var(--wall-type-system-sans, system-ui, sans-serif)
307
+ );
308
+ font-size: 1.25rem;
309
+ font-style: normal;
310
+ font-weight: 500;
311
+ line-height: normal;
312
+ }
313
+
314
+ .apm__cta:disabled {
315
+ cursor: not-allowed;
316
+ }
317
+
318
+ .apm__cta[aria-busy="true"] {
319
+ position: relative;
320
+ cursor: not-allowed;
321
+ }
322
+
323
+ .apm__cta[aria-busy="true"] > * {
324
+ visibility: hidden;
325
+ }
326
+
327
+ .apm__cta[aria-busy="true"]::after {
328
+ content: '';
329
+ position: absolute;
330
+ left: 50%;
331
+ top: 50%;
332
+ margin-left: -0.625rem;
333
+ margin-top: -0.625rem;
334
+ width: 1.25rem;
335
+ height: 1.25rem;
336
+ border: 2px solid rgba(255, 255, 255, 0.2);
337
+ border-top-color: #fff;
338
+ border-radius: 50%;
339
+ animation: apm-cta-spinner 0.8s linear infinite;
340
+ }
341
+
342
+ @keyframes apm-cta-spinner {
343
+ to {
344
+ transform: rotate(360deg);
345
+ }
346
+ }
347
+
348
+ .apm__cta svg {
349
+ flex-shrink: 0;
350
+ display: block;
351
+ }
352
+
353
+ @media (min-width: 22.5rem) and (max-width: 37.5rem) {
354
+ .apm {
355
+ width: 24.375rem;
356
+ max-width: 24.375rem;
357
+ }
358
+ }
359
+
360
+ @media (min-width: 37.5625rem) {
361
+ .apm {
362
+ border-radius: 0.5rem;
363
+ }
364
+ }
365
+
366
+ @media (max-width: 22.4375rem) {
367
+ .apm {
368
+ width: 20rem;
369
+ max-width: 20rem;
370
+ }
371
+ }
372
+
373
+ @media (max-width: 26.1875rem) {
374
+ .apm__cta {
375
+ font-size: 1.125rem;
376
+ }
377
+ }
378
+ </style>
379
+
380
+ <div class="apm-overlay" id="apple-pay-modal-overlay">
381
+ <div
382
+ class="apm"
383
+ role="dialog"
384
+ aria-modal="true"
385
+ aria-labelledby="apple-pay-modal-offer-name"
386
+ id="apple-pay-modal"
387
+ tabindex="-1"
388
+ >
389
+ <button class="apm__close" id="apple-pay-modal-close" aria-label="Close">
390
+ <svg
391
+ aria-hidden="true"
392
+ xmlns="http://www.w3.org/2000/svg"
393
+ width="24"
394
+ height="24"
395
+ viewBox="0 0 24 24"
396
+ fill="none"
397
+ >
398
+ <g clip-path="url(#clip0_15712_93054)">
399
+ <rect width="24" height="24" fill="white" fill-opacity="0.01" />
400
+ <path
401
+ fill-rule="evenodd"
402
+ clip-rule="evenodd"
403
+ d="M0 0H24V24H0V0Z"
404
+ fill="white"
405
+ fill-opacity="0.01"
406
+ />
407
+ <path
408
+ fill-rule="evenodd"
409
+ clip-rule="evenodd"
410
+ d="M18.75 6.60964L17.3904 5.25L12 10.6404L6.60964 5.25L5.25 6.60964L10.6404 12L5.25 17.3904L6.60964 18.75L12 13.3596L17.3904 18.75L18.75 17.3904L13.3596 12L18.75 6.60964Z"
411
+ fill="#333333"
412
+ />
413
+ </g>
414
+ <defs>
415
+ <clipPath id="clip0_15712_93054">
416
+ <rect width="24" height="24" fill="white" />
417
+ </clipPath>
418
+ </defs>
419
+ </svg>
420
+ </button>
421
+ <p class="apm__offer-name" id="apple-pay-modal-offer-name"></p>
422
+ <p class="apm__due-today" id="apple-pay-modal-due-today"></p>
423
+ <hr class="apm__rule" />
424
+ <div class="apm__terms" id="apple-pay-modal-terms"></div>
425
+ <p class="apm__passive-terms" id="apple-pay-modal-passive-terms"></p>
426
+ <label
427
+ class="apm__checkbox-label"
428
+ id="apple-pay-modal-checkbox-label"
429
+ for="apple-pay-modal-checkbox"
430
+ >
431
+ <div class="apm__checkbox-wrapper">
432
+ <input
433
+ class="apm__checkbox-input"
434
+ type="checkbox"
435
+ id="apple-pay-modal-checkbox"
436
+ />
437
+ <span class="apm__checkbox-custom">
438
+ <svg
439
+ aria-hidden="true"
440
+ class="svg-unchecked"
441
+ width="24"
442
+ height="24"
443
+ viewBox="0 0 24 24"
444
+ fill="none"
445
+ xmlns="http://www.w3.org/2000/svg"
446
+ >
447
+ <path
448
+ d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"
449
+ fill="white"
450
+ stroke="#595959"
451
+ />
452
+ </svg>
453
+ <svg
454
+ aria-hidden="true"
455
+ class="svg-checked"
456
+ width="24"
457
+ height="24"
458
+ viewBox="0 0 24 24"
459
+ fill="none"
460
+ xmlns="http://www.w3.org/2000/svg"
461
+ >
462
+ <g clip-path="url(#clip0_20014_9555)">
463
+ <path
464
+ d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"
465
+ fill="#333333"
466
+ />
467
+ <path
468
+ d="M10.2857 17L6 12.6814L7.20857 11.4635L10.2857 14.5557L16.7914 8L18 9.22649L10.2857 17Z"
469
+ fill="white"
470
+ />
471
+ </g>
472
+ <defs>
473
+ <clipPath id="clip0_20014_9555">
474
+ <path
475
+ d="M2 6C2 3.79086 3.79086 2 6 2H18C20.2091 2 22 3.79086 22 6V18C22 20.2091 20.2091 22 18 22H6C3.79086 22 2 20.2091 2 18V6Z"
476
+ fill="white"
477
+ />
478
+ </clipPath>
479
+ </defs>
480
+ </svg>
481
+ <svg
482
+ aria-hidden="true"
483
+ class="svg-error"
484
+ width="24"
485
+ height="24"
486
+ viewBox="0 0 24 24"
487
+ fill="none"
488
+ xmlns="http://www.w3.org/2000/svg"
489
+ >
490
+ <path
491
+ d="M6 2.5H18C19.933 2.5 21.5 4.067 21.5 6V18C21.5 19.933 19.933 21.5 18 21.5H6C4.067 21.5 2.5 19.933 2.5 18V6C2.5 4.067 4.067 2.5 6 2.5Z"
492
+ fill="white"
493
+ stroke="#C91D42"
494
+ stroke-width="2"
495
+ />
496
+ </svg>
497
+ </span>
498
+ </div>
499
+ <span id="apple-pay-modal-checkbox-text"></span>
500
+ </label>
501
+ <div class="apm__error" id="apple-pay-modal-error" role="alert">
502
+ <svg
503
+ aria-hidden="true"
504
+ width="20"
505
+ height="20"
506
+ viewBox="0 0 20 20"
507
+ fill="none"
508
+ xmlns="http://www.w3.org/2000/svg"
509
+ >
510
+ <path
511
+ fill-rule="evenodd"
512
+ clip-rule="evenodd"
513
+ d="M10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2ZM0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10ZM11 13C11 13.5523 10.5523 14 10 14C9.44772 14 9 13.5523 9 13C9 12.4477 9.44772 12 10 12C10.5523 12 11 12.4477 11 13ZM10 6C10.5523 6 11 6.44772 11 7V10C11 10.5523 10.5523 11 10 11C9.44772 11 9 10.5523 9 10V7C9 6.44772 9.44772 6 10 6Z"
514
+ fill="#C91D42"
515
+ />
516
+ </svg>
517
+ Please accept the terms to continue
518
+ </div>
519
+ <button class="apm__cta" id="apple-pay-modal-cta" aria-label="Continue with Apple Pay">
520
+ <span class="apm__cta-content">
521
+ Continue with
522
+ <svg width="51" height="22" aria-hidden="true" role="img">
523
+ <use href="#apple-pay-logo" />
524
+ </svg>
525
+ </span>
526
+ </button>
527
+ </div>
528
+ </div>
529
+
530
+ `;
531
+
532
+ // src/clients/payment-checkout/config.ts
533
+ var runtimeConfig = null;
534
+ var configureApplePay = (config) => {
535
+ runtimeConfig = {
536
+ ...config
537
+ };
538
+ };
539
+ var getApplePayConfig = () => runtimeConfig;
540
+
541
+ // src/utils/recaptcha.ts
542
+ var loadRecaptchaScript = (siteKey) => {
543
+ return new Promise((resolve, reject) => {
544
+ if (typeof grecaptcha !== "undefined") return resolve();
545
+ const existingScript = document.querySelector(
546
+ 'script[src*="recaptcha/api.js"]'
547
+ );
548
+ if (existingScript) {
549
+ existingScript.addEventListener("load", () => resolve());
550
+ existingScript.addEventListener(
551
+ "error",
552
+ () => reject(new Error("Failed to load existing reCAPTCHA script"))
553
+ );
554
+ return;
555
+ }
556
+ const script = document.createElement("script");
557
+ script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
558
+ script.async = true;
559
+ script.defer = true;
560
+ script.onload = () => resolve();
561
+ script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
562
+ document.head.appendChild(script);
563
+ });
564
+ };
565
+ var getRecaptchaToken = async (action) => {
566
+ const siteKey = getApplePayConfig()?.recaptchaSiteKey;
567
+ if (!siteKey) {
568
+ throw new Error(
569
+ "[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
570
+ );
571
+ }
572
+ await loadRecaptchaScript(siteKey);
573
+ return new Promise((resolve, reject) => {
574
+ grecaptcha.ready(() => {
575
+ grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
576
+ });
577
+ });
578
+ };
579
+ var getPurchaseRecaptchaTokens = async () => {
580
+ const [checkEligibility, newBasket, registerUser] = await Promise.all([
581
+ getRecaptchaToken("checkEligibility"),
582
+ getRecaptchaToken("newBasket"),
583
+ getRecaptchaToken("registerUser")
584
+ ]);
585
+ return { checkEligibility, newBasket, registerUser };
586
+ };
80
587
 
81
588
  // src/apple-pay-modal.ts
82
589
  function getRenewalDateText(unit, duration) {
@@ -128,6 +635,7 @@ function getOfferTypeText(offerType) {
128
635
  }
129
636
  var TERMS_LINK = '<a href="https://www.economistgroup.com/terms-of-use" target="_blank" rel="noopener noreferrer">Terms and Conditions</a>';
130
637
  var PRIVACY_LINK = '<a href="https://www.economistgroup.com/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a>';
638
+ var MSG_RECAPTCHA_LOAD_ERROR = "Something went wrong. Please close and try again.";
131
639
  function getCheckboxTermsHtml(isNYT, isLoggedIn, autoRenewal) {
132
640
  const autoRenewalClause = autoRenewal ? " and auto-renewal terms above," : "";
133
641
  if (isNYT) {
@@ -297,6 +805,19 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
297
805
  #country = "";
298
806
  #triggerElement = null;
299
807
  #keyHandler = null;
808
+ #recaptchaTokens = null;
809
+ #recaptchaTokensPromise = null;
810
+ /**
811
+ * Synchronous callback invoked directly from the CTA click handler once the
812
+ * user confirms. The caller (ApplePayButton) must call startApplePaySession
813
+ * inside this callback to preserve the browser's user-gesture chain — Safari
814
+ * requires new ApplePaySession() to execute within the original click stack.
815
+ *
816
+ * reCAPTCHA tokens are guaranteed non-null here: the CTA remains disabled
817
+ * until the token pre-fetch resolves, so this callback is never reached
818
+ * without valid tokens.
819
+ */
820
+ onConfirm = null;
300
821
  set offer(value) {
301
822
  this.#offer = value;
302
823
  }
@@ -391,27 +912,57 @@ var ApplePayModal = class _ApplePayModal extends HTMLElement {
391
912
  }
392
913
  });
393
914
  }
915
+ if (this.#recaptchaTokensPromise) {
916
+ if (cta) {
917
+ cta.setAttribute("disabled", "");
918
+ cta.setAttribute("aria-disabled", "true");
919
+ cta.setAttribute("aria-busy", "true");
920
+ }
921
+ this.#recaptchaTokensPromise.then((tokens) => {
922
+ this.#recaptchaTokens = tokens;
923
+ if (cta) {
924
+ cta.removeAttribute("disabled");
925
+ cta.removeAttribute("aria-disabled");
926
+ cta.removeAttribute("aria-busy");
927
+ }
928
+ }).catch(() => {
929
+ console.error("[web-apple-pay] apple-pay-modal: failed to pre-fetch reCAPTCHA tokens; CTA remains disabled");
930
+ if (cta) {
931
+ cta.removeAttribute("aria-busy");
932
+ }
933
+ const existingError = this.querySelector("#apple-pay-modal-error");
934
+ if (existingError) {
935
+ const icon = existingError.querySelector("svg");
936
+ existingError.textContent = MSG_RECAPTCHA_LOAD_ERROR;
937
+ if (icon) existingError.prepend(icon);
938
+ existingError.classList.add("apm__error--visible");
939
+ } else {
940
+ const errorNotice = document.createElement("div");
941
+ errorNotice.setAttribute("role", "alert");
942
+ errorNotice.className = "apm__error apm__error--visible";
943
+ errorNotice.textContent = MSG_RECAPTCHA_LOAD_ERROR;
944
+ cta?.insertAdjacentElement("beforebegin", errorNotice);
945
+ }
946
+ });
947
+ }
394
948
  cta?.addEventListener("click", () => {
395
949
  if (isUS && checkbox && !checkbox.checked) {
396
950
  errorElement?.classList.add("apm__error--visible");
397
951
  checkboxLabel?.classList.add("apm__checkbox-label--error");
398
952
  return;
399
953
  }
400
- this.dispatchEvent(
401
- new CustomEvent("apple-pay-confirmed", {
402
- bubbles: true,
403
- composed: true,
404
- detail: { skuId: offer.sku_id, country }
405
- })
406
- );
407
- this.close();
954
+ if (this.#recaptchaTokens) {
955
+ this.onConfirm?.(this.#recaptchaTokens);
956
+ this.close();
957
+ }
408
958
  });
409
959
  this.querySelector("#apple-pay-modal-close")?.addEventListener(
410
960
  "click",
411
961
  () => this.close()
412
962
  );
413
963
  }
414
- open() {
964
+ open(recaptchaTokensPromise) {
965
+ this.#recaptchaTokensPromise = recaptchaTokensPromise ?? getPurchaseRecaptchaTokens();
415
966
  this.#triggerElement = document.activeElement;
416
967
  document.body.appendChild(this);
417
968
  this.#keyHandler = (event) => {
@@ -524,15 +1075,6 @@ var apple_pay_button_template_default = `<style>
524
1075
  </div>
525
1076
  `;
526
1077
 
527
- // src/clients/payment-checkout/config.ts
528
- var runtimeConfig = null;
529
- var configureApplePay = (config) => {
530
- runtimeConfig = {
531
- ...config
532
- };
533
- };
534
- var getApplePayConfig = () => runtimeConfig;
535
-
536
1078
  // src/clients/payment-checkout/detects.ts
537
1079
  var isAppleDeviceOrSafari = () => {
538
1080
  const isIOSOrMacTouchDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.maxTouchPoints > 1 && /Macintosh/.test(navigator.userAgent);
@@ -565,7 +1107,8 @@ var isApplePayAvailable = async () => {
565
1107
  );
566
1108
  return false;
567
1109
  }
568
- return await applePaySession.canMakePaymentsWithActiveCard(merchantId);
1110
+ const hasActiveCard = await applePaySession.canMakePaymentsWithActiveCard(merchantId);
1111
+ return hasActiveCard;
569
1112
  } catch (error) {
570
1113
  console.error("Error checking Apple Pay active card status:", error);
571
1114
  return false;
@@ -694,53 +1237,6 @@ var redirectToCheckoutFallback = (params) => {
694
1237
  return url.pathname + url.search;
695
1238
  };
696
1239
 
697
- // src/utils/recaptcha.ts
698
- var loadRecaptchaScript = (siteKey) => {
699
- return new Promise((resolve, reject) => {
700
- if (typeof grecaptcha !== "undefined") return resolve();
701
- const existingScript = document.querySelector(
702
- 'script[src*="recaptcha/api.js"]'
703
- );
704
- if (existingScript) {
705
- existingScript.addEventListener("load", () => resolve());
706
- existingScript.addEventListener(
707
- "error",
708
- () => reject(new Error("Failed to load existing reCAPTCHA script"))
709
- );
710
- return;
711
- }
712
- const script = document.createElement("script");
713
- script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
714
- script.async = true;
715
- script.defer = true;
716
- script.onload = () => resolve();
717
- script.onerror = () => reject(new Error("Failed to load reCAPTCHA script"));
718
- document.head.appendChild(script);
719
- });
720
- };
721
- var getRecaptchaToken = async (action) => {
722
- const siteKey = getApplePayConfig()?.recaptchaSiteKey;
723
- if (!siteKey) {
724
- throw new Error(
725
- "[web-apple-pay] Missing recaptchaSiteKey. Call configureApplePay({ recaptchaSiteKey, ... }) before initiating Apple Pay."
726
- );
727
- }
728
- await loadRecaptchaScript(siteKey);
729
- return new Promise((resolve, reject) => {
730
- grecaptcha.ready(() => {
731
- grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
732
- });
733
- });
734
- };
735
- var getPurchaseRecaptchaTokens = async () => {
736
- const [checkEligibility, newBasket, registerUser] = await Promise.all([
737
- getRecaptchaToken("checkEligibility"),
738
- getRecaptchaToken("newBasket"),
739
- getRecaptchaToken("registerUser")
740
- ]);
741
- return { checkEligibility, newBasket, registerUser };
742
- };
743
-
744
1240
  // src/utils/expressCheckoutTracking.ts
745
1241
  var EXPRESS_CHECKOUT_EVENTS = {
746
1242
  /** Wallet button displayed */
@@ -853,7 +1349,8 @@ async function handleMerchantValidation(event, session, config) {
853
1349
  return;
854
1350
  }
855
1351
  session.completeMerchantValidation(response.merchantSession);
856
- } catch {
1352
+ } catch (err) {
1353
+ console.error("[web-apple-pay] onvalidatemerchant: error during validation", err);
857
1354
  session.abort();
858
1355
  redirectToFallbackCheckout(config);
859
1356
  }
@@ -886,7 +1383,8 @@ function startApplePaySession(config) {
886
1383
  };
887
1384
  trackWalletPaymentSheetOpen(config.skuId);
888
1385
  session.begin();
889
- } catch {
1386
+ } catch (err) {
1387
+ console.error("[web-apple-pay] startApplePaySession: failed to create session", err);
890
1388
  redirectToFallbackCheckout(config);
891
1389
  }
892
1390
  }
@@ -1074,6 +1572,7 @@ async function handlePaymentAuthorized(event, session, sessionData, config) {
1074
1572
  const result = await performPurchase({
1075
1573
  applePayToken: event.payment.token,
1076
1574
  skuId: config.skuId,
1575
+ currency: config.currency,
1077
1576
  billingContact: event.payment.billingContact,
1078
1577
  ...event.payment.shippingContact && {
1079
1578
  shippingContact: event.payment.shippingContact
@@ -1402,7 +1901,9 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1402
1901
  const button = document.createElement(_ApplePayButton.tag);
1403
1902
  button.offer = offer;
1404
1903
  button.country = country;
1405
- button.entryPoint = entryPoint;
1904
+ if (entryPoint) {
1905
+ button.entryPoint = entryPoint;
1906
+ }
1406
1907
  return button;
1407
1908
  }
1408
1909
  /**
@@ -1424,7 +1925,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1424
1925
  #returnUrl = "";
1425
1926
  #supportedBillingCountries = [];
1426
1927
  #entryPoint = "";
1427
- #recaptchaTokens = null;
1928
+ #recaptchaTokensPromise = null;
1428
1929
  // ─── Public API ─────────────────────────────────────────────────────────────
1429
1930
  get offer() {
1430
1931
  return this.#offer;
@@ -1489,6 +1990,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1489
1990
  this.#paymentOptions = null;
1490
1991
  this.#returnUrl = "";
1491
1992
  this.#supportedBillingCountries = [];
1993
+ this.#recaptchaTokensPromise = null;
1492
1994
  this.querySelector(SEL_CONTAINER)?.remove();
1493
1995
  }
1494
1996
  // ─── Render pipeline ────────────────────────────────────────────────────────
@@ -1502,7 +2004,8 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1502
2004
  this.#computeBillingCountries();
1503
2005
  if (await this.#fetchAndCacheOptions()) return;
1504
2006
  this.#finishLoading();
1505
- } catch {
2007
+ } catch (err) {
2008
+ console.error("[web-apple-pay] #run: unexpected error, hiding button", err);
1506
2009
  this.style.display = "none";
1507
2010
  this.querySelector(SEL_CONTAINER)?.remove();
1508
2011
  } finally {
@@ -1583,16 +2086,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1583
2086
  if (button.classList.contains("wap-loading")) return;
1584
2087
  this.#openModal();
1585
2088
  });
1586
- document.addEventListener("apple-pay-confirmed", (event) => {
1587
- const { skuId, country } = event.detail;
1588
- this.#initiateApplePay(skuId, country);
1589
- }, { once: true });
1590
2089
  }
1591
2090
  #finishLoading() {
1592
2091
  const button = this.querySelector(SEL_BUTTON);
1593
2092
  if (button) {
1594
2093
  button.classList.remove("wap-loading");
1595
2094
  this.#updateDisabledState();
2095
+ this.#scheduleRecaptchaTokens();
1596
2096
  trackExpressWalletImpression(this.#offer.sku_id, {
1597
2097
  entryPoint: this.#entryPoint,
1598
2098
  country: this.#country
@@ -1620,10 +2120,6 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1620
2120
  return;
1621
2121
  }
1622
2122
  trackExpressWalletClick(this.#offer.sku_id);
1623
- getPurchaseRecaptchaTokens().then((tokens) => {
1624
- this.#recaptchaTokens = tokens;
1625
- }).catch(() => {
1626
- });
1627
2123
  ApplePayModal.define();
1628
2124
  const modal = document.createElement(ApplePayModal.tag);
1629
2125
  modal.offer = this.#offer;
@@ -1631,7 +2127,30 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1631
2127
  if (this.#sessionData?.loggedIn) {
1632
2128
  modal.dataset.loggedIn = "true";
1633
2129
  }
1634
- modal.open();
2130
+ const skuId = this.#offer.sku_id;
2131
+ const country = this.#country;
2132
+ modal.onConfirm = (recaptchaTokens) => {
2133
+ this.#initiateApplePay(skuId, country, recaptchaTokens);
2134
+ this.#scheduleRecaptchaTokens();
2135
+ };
2136
+ modal.open(this.#recaptchaTokensPromise);
2137
+ }
2138
+ /**
2139
+ * Starts a fresh reCAPTCHA token pre-fetch and stores its promise.
2140
+ * If the fetch rejects, the field is cleared so the next `modal.open()` call
2141
+ * falls back to a new attempt via the modal's own null-fallback path — preventing
2142
+ * a single transient failure from permanently disabling the CTA on all retries.
2143
+ * The identity guard prevents a late rejection from clobbering a newer attempt.
2144
+ */
2145
+ #scheduleRecaptchaTokens() {
2146
+ const attempt = getPurchaseRecaptchaTokens();
2147
+ attempt.catch((err) => {
2148
+ console.error("[web-apple-pay] reCAPTCHA token pre-fetch failed; will retry on modal open", err);
2149
+ if (this.#recaptchaTokensPromise === attempt) {
2150
+ this.#recaptchaTokensPromise = null;
2151
+ }
2152
+ });
2153
+ this.#recaptchaTokensPromise = attempt;
1635
2154
  }
1636
2155
  async #fetchSession() {
1637
2156
  try {
@@ -1667,6 +2186,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1667
2186
  onPaymentAuthorized: (event, session) => handlePaymentAuthorized(event, session, sessionData, {
1668
2187
  skuId,
1669
2188
  country,
2189
+ currency: offer.price?.currency_code ?? DEFAULT_CURRENCY,
1670
2190
  returnUrl: this.#returnUrl,
1671
2191
  queryString: buildQueryString(),
1672
2192
  supportedBillingCountries: this.#supportedBillingCountries,
@@ -1674,11 +2194,10 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1674
2194
  })
1675
2195
  };
1676
2196
  }
1677
- async #initiateApplePay(skuId, country) {
2197
+ #initiateApplePay(skuId, country, recaptchaTokens) {
1678
2198
  try {
1679
2199
  const sessionData = this.#sessionData ?? _ApplePayButton.#ANONYMOUS_SESSION;
1680
2200
  const paymentOptions = this.#paymentOptions;
1681
- const recaptchaTokens = this.#recaptchaTokens ?? await getPurchaseRecaptchaTokens();
1682
2201
  startApplePaySession(
1683
2202
  this.#buildSessionParams(
1684
2203
  skuId,
@@ -1694,6 +2213,13 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
1694
2213
  }
1695
2214
  };
1696
2215
 
2216
+ // src/constants.ts
2217
+ var ApplePayEntryPoint = /* @__PURE__ */ ((ApplePayEntryPoint2) => {
2218
+ ApplePayEntryPoint2["PAYWALL"] = "article_paywall";
2219
+ ApplePayEntryPoint2["REGWALL"] = "article_regwall";
2220
+ return ApplePayEntryPoint2;
2221
+ })(ApplePayEntryPoint || {});
2222
+
1697
2223
  // src/index.ts
1698
2224
  function defineApplePayElements() {
1699
2225
  ApplePayButton.define();
@@ -1702,6 +2228,7 @@ function defineApplePayElements() {
1702
2228
  export {
1703
2229
  APPLE_PAY_EXCLUDED_VARIANTS,
1704
2230
  ApplePayButton,
2231
+ ApplePayEntryPoint,
1705
2232
  ApplePayModal,
1706
2233
  configureApplePay,
1707
2234
  defineApplePayElements,