@maytes/checkout-button 1.0.1 → 1.1.1
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/CHANGELOG.md +62 -0
- package/README.md +38 -11
- package/dist/{checkout-button.6d259930.cjs → checkout-button.2aad12c3.cjs} +100 -28
- package/dist/checkout-button.2aad12c3.cjs.map +1 -0
- package/dist/checkout-button.4b780d52.js +151 -0
- package/dist/checkout-button.4b780d52.js.map +1 -0
- package/dist/{checkout-button.81ea2037.mjs → checkout-button.aed57a66.mjs} +100 -28
- package/dist/checkout-button.aed57a66.mjs.map +1 -0
- package/dist/checkout-button.cjs +100 -28
- package/dist/checkout-button.cjs.map +1 -1
- package/dist/checkout-button.d.cts +12 -2
- package/dist/checkout-button.d.ts +12 -2
- package/dist/checkout-button.js +4 -4
- package/dist/checkout-button.js.map +1 -1
- package/dist/checkout-button.mjs +100 -28
- package/dist/checkout-button.mjs.map +1 -1
- package/dist/integrity.json +26 -26
- package/package.json +3 -1
- package/dist/checkout-button.6d259930.cjs.map +0 -1
- package/dist/checkout-button.81ea2037.mjs.map +0 -1
- package/dist/checkout-button.8c71493e.js +0 -151
- package/dist/checkout-button.8c71493e.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,66 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#16](https://github.com/kttipay/maytes-checkout-button/pull/16) [`e0bd228`](https://github.com/kttipay/maytes-checkout-button/commit/e0bd228f454979c6dd41587cb0e82e9fe735a888) Thanks [@kttipaydiogocavaiar](https://github.com/kttipaydiogocavaiar)! - The popup loading overlay no longer outlives the frame that opened it. When the button runs inside a same-origin iframe, the "Completing checkout with Maytes…" dialog is mounted in the top-level document so it covers the whole merchant page, but only the frame's SDK instance could remove it. The hosted checkout's back, cancel and return exits navigate `window.opener`, which is that frame, so the frame's document was replaced, its popup poll died, and the merchant page stayed covered by a modal dialog with the button unreachable. The overlay now also listens for the frame's `pagehide` and removes itself from the top-level document when the frame navigates away.
|
|
8
|
+
|
|
9
|
+
<!-- @hash-sri-start -->
|
|
10
|
+
|
|
11
|
+
**SRI hashes** (use these in `<script integrity="..." crossorigin="anonymous">`):
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
checkout-button.js sha384-dfHU/wrTbetBPk5TdX9haImZAq87uFVrlMKMSept0sgtIbTqdYWQi2ml8BF6Gq8N
|
|
15
|
+
checkout-button.mjs sha384-JKjUqX0jqi7UoqqNYGlD97mTCeR0ZshbiLtXhfPQl2w5mQtfmBx+X7W95SjjmkkY
|
|
16
|
+
checkout-button.cjs sha384-oSekYX0Re0jdMsBU6uzxUedTM+Cnl8uF5y0wmZmjUHngtzr8Sdze1MrOSYkGXKJ3
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**SemVer CDN links** (readable production pins; use with the SRI hashes above):
|
|
20
|
+
|
|
21
|
+
- [checkout-button.js](https://js.maytes.co/v1.1.1/checkout-button.js)
|
|
22
|
+
- [checkout-button.mjs](https://js.maytes.co/v1.1.1/checkout-button.mjs)
|
|
23
|
+
- [checkout-button.cjs](https://js.maytes.co/v1.1.1/checkout-button.cjs)
|
|
24
|
+
|
|
25
|
+
**Hashed CDN links** (byte-level production pins; use with the SRI hashes above):
|
|
26
|
+
|
|
27
|
+
- [checkout-button.4b780d52.js](https://js.maytes.co/checkout-button.4b780d52.js)
|
|
28
|
+
- [checkout-button.aed57a66.mjs](https://js.maytes.co/checkout-button.aed57a66.mjs)
|
|
29
|
+
- [checkout-button.2aad12c3.cjs](https://js.maytes.co/checkout-button.2aad12c3.cjs)
|
|
30
|
+
|
|
31
|
+
<!-- @hash-sri-end -->
|
|
32
|
+
## 1.1.0
|
|
33
|
+
|
|
34
|
+
### Minor Changes
|
|
35
|
+
|
|
36
|
+
- [#11](https://github.com/kttipay/maytes-checkout-button/pull/11) [`def33e0`](https://github.com/kttipay/maytes-checkout-button/commit/def33e010bf23b11bc94871e236d35a65deb825e) Thanks [@kos-maytes](https://github.com/kos-maytes)! - `renderButton`'s default `mode` is now `'popup'` instead of `'redirect'`. Pass `mode: 'redirect'` explicitly to keep the previous same-window navigation behavior. Popup mode already falls back to same-window redirect on mobile viewports and when the popup is blocked, so this only changes the desktop no-`mode`-specified path.
|
|
37
|
+
|
|
38
|
+
- [#8](https://github.com/kttipay/maytes-checkout-button/pull/8) [`a6d85e2`](https://github.com/kttipay/maytes-checkout-button/commit/a6d85e23653e340b7a850ad61e882ec2f6cef5d2) Thanks [@kttipaydiogocavaiar](https://github.com/kttipaydiogocavaiar)! - The button never loads the hosted checkout inside an iframe any more. When the button is rendered inside a frame (for example a booking widget embedded on the merchant's page), a phone or a narrow frame used to take the same-window fallback and navigate the frame itself, so the checkout ran as a cross-site iframe where its session cookie is rejected and sign-in ended on "Your session expired". The button now measures the top-level window (or the screen when the top window is cross-origin) and navigates the top-level window; if the browser refuses, it opens the checkout in a new tab; if both are refused, it dispatches `maytes:checkout-failed` with `reason: 'navigation-blocked'` and leaves the button usable. `maytes:checkout-redirected` now carries `detail.target` (`'self' | 'top' | 'tab'`). `redirectToCheckout()` follows the same rule and throws `MaytesError` when it cannot leave the frame. Merchants who deliberately relied on in-frame navigation will see the top-level page change instead; render the button in the top-level page if that is not wanted.
|
|
39
|
+
|
|
40
|
+
<!-- @hash-sri-start -->
|
|
41
|
+
|
|
42
|
+
**SRI hashes** (use these in `<script integrity="..." crossorigin="anonymous">`):
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
checkout-button.js sha384-+hQ9khxZbVEUhR685659hqmPyN/3RYfbNEI7itac3SkcyYor/94/0mIwVnVwMa8M
|
|
46
|
+
checkout-button.mjs sha384-1areqNcTs9sephTl6S1+sOgACv1/NqIqXBG0Ej11/4OfSDcN92GvQvhhu4K76R5i
|
|
47
|
+
checkout-button.cjs sha384-4c1JuweT47cnpvGlQfv+qQw/3CS+7o2/Dg4qQnLiWM1GDChhHQo0dT+z8705Hy50
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**SemVer CDN links** (readable production pins; use with the SRI hashes above):
|
|
51
|
+
|
|
52
|
+
- [checkout-button.js](https://js.maytes.co/v1.1.0/checkout-button.js)
|
|
53
|
+
- [checkout-button.mjs](https://js.maytes.co/v1.1.0/checkout-button.mjs)
|
|
54
|
+
- [checkout-button.cjs](https://js.maytes.co/v1.1.0/checkout-button.cjs)
|
|
55
|
+
|
|
56
|
+
**Hashed CDN links** (byte-level production pins; use with the SRI hashes above):
|
|
57
|
+
|
|
58
|
+
- [checkout-button.811263f9.js](https://js.maytes.co/checkout-button.811263f9.js)
|
|
59
|
+
- [checkout-button.f96c49ee.mjs](https://js.maytes.co/checkout-button.f96c49ee.mjs)
|
|
60
|
+
- [checkout-button.178d8394.cjs](https://js.maytes.co/checkout-button.178d8394.cjs)
|
|
61
|
+
|
|
62
|
+
<!-- @hash-sri-end -->
|
|
63
|
+
|
|
3
64
|
## 1.0.1
|
|
4
65
|
|
|
5
66
|
### Patch Changes
|
|
@@ -29,6 +90,7 @@ checkout-button.cjs sha384-+O2S6KfO4Pc0VEvL+kTsFzxU14W4EILV6+U5mAdW8X43Xm8Qk1aV
|
|
|
29
90
|
- [checkout-button.6d259930.cjs](https://js.maytes.co/checkout-button.6d259930.cjs)
|
|
30
91
|
|
|
31
92
|
<!-- @hash-sri-end -->
|
|
93
|
+
|
|
32
94
|
## 1.0.0
|
|
33
95
|
|
|
34
96
|
First public release on npm.
|
package/README.md
CHANGED
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
Renders a button and launches the Maytes-hosted checkout
|
|
21
|
+
Renders a button and launches the Maytes-hosted checkout in the top-level window. Default mode opens a centered popup on wide viewports, with a branded loader and automatic redirect fallback on phones or when the popup is blocked; `mode: 'redirect'` opts into a redirect always. Inside an iframe every redirect targets the top-level window.
|
|
22
22
|
|
|
23
23
|
**📖 Full integration guide:** [developers.maytes.co/checkout-button](https://developers.maytes.co/checkout-button)
|
|
24
24
|
|
|
25
25
|
- **Framework-agnostic** — same factory whether it's a `<script>` tag or `import { Maytes }`; no React/Vue/Angular binding to keep in sync.
|
|
26
26
|
- **Zero runtime dependencies** — a small, dependency-free bundle; ESM/CJS ship unminified so your bundler can tree-shake it.
|
|
27
27
|
- **CSP-safe by construction** — no `eval`, `Function`, or string-form timers; every release is scanned for it before shipping.
|
|
28
|
-
- **
|
|
28
|
+
- **Evergreen CDN by default** — the recommended `<script>` tag always serves the newest release; pin a SemVer or content-hash URL instead if you'd rather freeze on a tested build.
|
|
29
29
|
- **Signed provenance** — every npm release carries a [SLSA](https://slsa.dev) provenance attestation back to this repo's build.
|
|
30
30
|
|
|
31
31
|
## Contents
|
|
@@ -40,23 +40,46 @@ Renders a button and launches the Maytes-hosted checkout. Default mode is same-w
|
|
|
40
40
|
|
|
41
41
|
### Script tag (CDN)
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
| | Evergreen (recommended) | Pinned |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| **Use when** | Default — always get the newest `1.x` release | You'd rather freeze on a tested build |
|
|
46
|
+
| **Guarantee** | Always current; a bad release reaches you immediately | The bytes you tested are the bytes shipped, forever |
|
|
47
|
+
| **SRI** | Not possible | Yes |
|
|
48
|
+
|
|
49
|
+
### Evergreen (recommended)
|
|
44
50
|
|
|
45
51
|
```html
|
|
46
|
-
<script src="https://js.maytes.co/v1
|
|
47
|
-
integrity="sha384-…"
|
|
52
|
+
<script src="https://js.maytes.co/v1/checkout-button.js"
|
|
48
53
|
crossorigin="anonymous"></script>
|
|
49
54
|
```
|
|
50
55
|
|
|
56
|
+
No `integrity` attribute is possible here — the bytes change without notice as new `1.x` releases ship. Trust the origin via CSP instead:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Content-Security-Policy: script-src 'self' https://js.maytes.co;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`/v1/` tracks the newest `1.x` release only; it won't jump to a future `2.x` (move to `/v2/checkout-button.js` explicitly once that ships). Poll `https://js.maytes.co/integrity.json` if you want to detect changes yourself.
|
|
63
|
+
|
|
64
|
+
### Pinned (SemVer or content hash)
|
|
65
|
+
|
|
66
|
+
For a guarantee instead of convenience — freeze on a tested build, update on your own schedule:
|
|
67
|
+
|
|
68
|
+
<!-- @cdn-example-start -->
|
|
51
69
|
```html
|
|
52
|
-
<script src="https://js.maytes.co/checkout-button.
|
|
70
|
+
<script src="https://js.maytes.co/v1.1.1/checkout-button.js"
|
|
53
71
|
integrity="sha384-…"
|
|
54
72
|
crossorigin="anonymous"></script>
|
|
55
73
|
```
|
|
56
74
|
|
|
57
|
-
|
|
75
|
+
```html
|
|
76
|
+
<script src="https://js.maytes.co/checkout-button.4b780d52.js"
|
|
77
|
+
integrity="sha384-…"
|
|
78
|
+
crossorigin="anonymous"></script>
|
|
79
|
+
```
|
|
80
|
+
<!-- @cdn-example-end -->
|
|
58
81
|
|
|
59
|
-
|
|
82
|
+
Both URLs are the same release bytes with the same SRI value — pick either. Full version/hash/SRI history: [`CHANGELOG.md`](./CHANGELOG.md), [releases](https://github.com/kttipay/maytes-checkout-button/releases), `https://js.maytes.co/integrity.json`. Pinned URLs never change once published.
|
|
60
83
|
|
|
61
84
|
### npm
|
|
62
85
|
|
|
@@ -81,8 +104,8 @@ const maytes = Maytes({
|
|
|
81
104
|
|
|
82
105
|
const cleanup = maytes.renderButton(document.getElementById('slot'), { block: true });
|
|
83
106
|
|
|
84
|
-
//
|
|
85
|
-
maytes.renderButton(document.getElementById('
|
|
107
|
+
// Opt into same-window redirect instead of the default popup:
|
|
108
|
+
maytes.renderButton(document.getElementById('redirect-slot'), { block: true, mode: 'redirect' });
|
|
86
109
|
|
|
87
110
|
// Imperative alternatives:
|
|
88
111
|
maytes.redirectToCheckout({ checkoutId });
|
|
@@ -100,11 +123,15 @@ Via the script tag, the same factory is available as the global `window.Maytes(.
|
|
|
100
123
|
| Method | Purpose |
|
|
101
124
|
|---|---|
|
|
102
125
|
| `Maytes(options)` | Create an SDK instance. `options.createCheckout` mints a checkout server-side; `options.environment` selects the Maytes environment. |
|
|
103
|
-
| `renderButton(container, options?)` | Render the button into `container`; returns a cleanup function. Options include `label`, `block`, and `mode: 'redirect' \| 'popup'
|
|
126
|
+
| `renderButton(container, options?)` | Render the button into `container`; returns a cleanup function. Options include `label`, `block`, and `mode: 'redirect' \| 'popup'` (default `'popup'`). |
|
|
104
127
|
| `redirectToCheckout(options)` | Launch checkout directly (no button). |
|
|
105
128
|
| `checkoutUrl(options)` | Build the hosted checkout URL. |
|
|
106
129
|
| `destroy()` | Tear down the instance and its listeners — call this on unmount or when the instance's config/environment changes, not as a reaction to detecting payment success from your own polling (that can tear down a checkout that's still in progress). To remove a single button, use the cleanup function returned by `renderButton()` or hide/disable the button element instead. |
|
|
107
130
|
|
|
131
|
+
### Inside an iframe?
|
|
132
|
+
|
|
133
|
+
The hosted checkout must run in the top-level window (its session cookie is refused inside a cross-site frame). If you render the button inside an iframe, the SDK navigates the top-level window; if the browser refuses, it opens a new tab; if both are refused it dispatches `maytes:checkout-failed` with `reason: 'navigation-blocked'`. When the checkout opens in a new tab, no popup poll starts and no `maytes:checkout-opened` / `maytes:checkout-closed` pair fires — you'll only see `maytes:checkout-redirected` with `target: 'tab'`. A sandboxed iframe needs `allow-scripts allow-same-origin allow-top-navigation` (plus `allow-popups allow-popups-to-escape-sandbox` for the tab fallback). Listen to `maytes:checkout-redirected` and read `event.detail.target` (`'self'`, `'top'` or `'tab'`) if your page needs to know where the checkout went. Rendering the button in the top-level page avoids all of this.
|
|
134
|
+
|
|
108
135
|
## Mobile app
|
|
109
136
|
|
|
110
137
|
After checkout, shoppers split the cost with friends using Maytes payment links (`app.maytes.co/…`). On a phone with the Maytes app installed, those links open directly in the app (iOS Universal Links / Android App Links); otherwise they open in the browser. Maytes handles this end to end — merchants integrate only the button and configure nothing for the app.
|
|
@@ -86,21 +86,79 @@ var MaytesError = class extends Error {
|
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
+
// src/framing.ts
|
|
90
|
+
function isSecurityError(err) {
|
|
91
|
+
return typeof err === "object" && err !== null && err.name === "SecurityError";
|
|
92
|
+
}
|
|
93
|
+
function isFramed() {
|
|
94
|
+
return window.top !== null && window.top !== window;
|
|
95
|
+
}
|
|
96
|
+
function sameOriginTop() {
|
|
97
|
+
if (!isFramed()) return null;
|
|
98
|
+
const top = window.top;
|
|
99
|
+
try {
|
|
100
|
+
void top.document;
|
|
101
|
+
return top;
|
|
102
|
+
} catch (err) {
|
|
103
|
+
if (!isSecurityError(err)) throw err;
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function viewportWidth() {
|
|
108
|
+
if (!isFramed()) return window.innerWidth;
|
|
109
|
+
const top = sameOriginTop();
|
|
110
|
+
if (top !== null) return top.innerWidth;
|
|
111
|
+
const screenWidth = window.screen?.width;
|
|
112
|
+
return typeof screenWidth === "number" && screenWidth > 0 ? screenWidth : window.innerWidth;
|
|
113
|
+
}
|
|
114
|
+
function navigateWindow(target, url, replace) {
|
|
115
|
+
if (replace) {
|
|
116
|
+
target.location.replace(url);
|
|
117
|
+
} else {
|
|
118
|
+
target.location.href = url;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function severOpener(tab) {
|
|
122
|
+
try {
|
|
123
|
+
tab.opener = null;
|
|
124
|
+
} catch (err) {
|
|
125
|
+
if (!isSecurityError(err)) throw err;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function navigateTopLevel(url, replace) {
|
|
129
|
+
if (!isFramed()) {
|
|
130
|
+
navigateWindow(window, url, replace);
|
|
131
|
+
return { target: "self" };
|
|
132
|
+
}
|
|
133
|
+
let refusal;
|
|
134
|
+
try {
|
|
135
|
+
navigateWindow(window.top, url, replace);
|
|
136
|
+
return { target: "top" };
|
|
137
|
+
} catch (err) {
|
|
138
|
+
if (!isSecurityError(err)) throw err;
|
|
139
|
+
refusal = err;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const tab = window.open(url, "_blank");
|
|
143
|
+
if (tab !== null) {
|
|
144
|
+
severOpener(tab);
|
|
145
|
+
return { target: "tab" };
|
|
146
|
+
}
|
|
147
|
+
return { target: null, cause: refusal };
|
|
148
|
+
} catch (err) {
|
|
149
|
+
return { target: null, cause: err };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
89
153
|
// src/overlay.ts
|
|
90
154
|
var TITLE_ID = "maytes-overlay-title";
|
|
91
155
|
var STYLE_MARKER = "data-maytes-checkout-button-overlay-styles";
|
|
92
156
|
var NATIVE_BACKDROP_FALLBACK = "rgba(0, 0, 0, 0.6)";
|
|
93
157
|
function tryReadTopDocument() {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
} catch (err) {
|
|
99
|
-
if (!(err instanceof DOMException && err.name === "SecurityError")) {
|
|
100
|
-
console.warn("[maytes/checkout-button] unexpected error resolving overlay host", err);
|
|
101
|
-
}
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
158
|
+
const top = sameOriginTop();
|
|
159
|
+
if (top === null) return null;
|
|
160
|
+
const topDoc = top.document;
|
|
161
|
+
return topDoc.body !== null ? topDoc : null;
|
|
104
162
|
}
|
|
105
163
|
function resolveOverlayHost() {
|
|
106
164
|
return tryReadTopDocument() ?? document;
|
|
@@ -148,7 +206,7 @@ function buildOverlay(host, state) {
|
|
|
148
206
|
try {
|
|
149
207
|
state.popupWindow.focus();
|
|
150
208
|
} catch (err) {
|
|
151
|
-
if (!(err
|
|
209
|
+
if (!isSecurityError(err)) throw err;
|
|
152
210
|
}
|
|
153
211
|
}
|
|
154
212
|
});
|
|
@@ -171,6 +229,7 @@ function showOverlay(state) {
|
|
|
171
229
|
const dialog = buildOverlay(host, state);
|
|
172
230
|
state.overlayEl = dialog;
|
|
173
231
|
host.body.appendChild(dialog);
|
|
232
|
+
if (host !== document) detachOverlayWhenThisPageHides(state);
|
|
174
233
|
if (typeof dialog.showModal === "function") {
|
|
175
234
|
try {
|
|
176
235
|
dialog.showModal();
|
|
@@ -184,8 +243,15 @@ function showOverlay(state) {
|
|
|
184
243
|
applyNativeBackdropFallback(dialog);
|
|
185
244
|
}
|
|
186
245
|
}
|
|
246
|
+
function detachOverlayWhenThisPageHides(state) {
|
|
247
|
+
const onPageHide = () => hideOverlay(state);
|
|
248
|
+
window.addEventListener("pagehide", onPageHide);
|
|
249
|
+
state.overlayDetach = () => window.removeEventListener("pagehide", onPageHide);
|
|
250
|
+
}
|
|
187
251
|
function hideOverlay(state) {
|
|
188
252
|
if (state.overlayEl === null) return;
|
|
253
|
+
state.overlayDetach?.();
|
|
254
|
+
state.overlayDetach = null;
|
|
189
255
|
const dialog = state.overlayEl;
|
|
190
256
|
const host = dialog.ownerDocument;
|
|
191
257
|
if (typeof dialog.close === "function" && dialog.open) dialog.close();
|
|
@@ -258,10 +324,12 @@ function performRedirect(url, replace) {
|
|
|
258
324
|
"redirectToCheckout requires a browser context (window is undefined)"
|
|
259
325
|
);
|
|
260
326
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
327
|
+
const outcome = navigateTopLevel(url, replace);
|
|
328
|
+
if (outcome.target === null) {
|
|
329
|
+
throw new MaytesError(
|
|
330
|
+
MaytesErrorCode.Config,
|
|
331
|
+
"redirectToCheckout could not leave the embedding iframe; call it from a user gesture or from the top-level page"
|
|
332
|
+
);
|
|
265
333
|
}
|
|
266
334
|
}
|
|
267
335
|
function makeRedirect(environment, baseUrlOverride) {
|
|
@@ -277,7 +345,7 @@ function makeRedirect(environment, baseUrlOverride) {
|
|
|
277
345
|
}
|
|
278
346
|
|
|
279
347
|
// src/version.ts
|
|
280
|
-
var SDK_VERSION = "1.
|
|
348
|
+
var SDK_VERSION = "1.1.1";
|
|
281
349
|
|
|
282
350
|
// src/styles.ts
|
|
283
351
|
var STYLE_ATTR = "data-maytes-checkout-button";
|
|
@@ -488,9 +556,6 @@ function isValidCheckoutResult(value) {
|
|
|
488
556
|
}
|
|
489
557
|
return true;
|
|
490
558
|
}
|
|
491
|
-
function isSecurityError(err) {
|
|
492
|
-
return err instanceof DOMException && err.name === "SecurityError";
|
|
493
|
-
}
|
|
494
559
|
function refocusPopup(popup) {
|
|
495
560
|
try {
|
|
496
561
|
popup.focus();
|
|
@@ -531,7 +596,7 @@ function startPopupPoll(state, onClose) {
|
|
|
531
596
|
}, POPUP_POLL_INTERVAL_MS);
|
|
532
597
|
}
|
|
533
598
|
function isMobileViewport() {
|
|
534
|
-
return
|
|
599
|
+
return viewportWidth() <= MOBILE_MAX_WIDTH;
|
|
535
600
|
}
|
|
536
601
|
function openBlankPopup(state) {
|
|
537
602
|
return window.open("about:blank", state.popupName, popupFeatures());
|
|
@@ -592,7 +657,7 @@ function renderButton(state, container, options = {}) {
|
|
|
592
657
|
ensureStylesInjected(state.config.cspNonce);
|
|
593
658
|
const label = options.label ?? "Split with";
|
|
594
659
|
const block = options.block === true;
|
|
595
|
-
const mode = options.mode ?? "
|
|
660
|
+
const mode = options.mode ?? "popup";
|
|
596
661
|
if (mode !== "redirect" && mode !== "popup") {
|
|
597
662
|
throw new MaytesError(
|
|
598
663
|
MaytesErrorCode.Config,
|
|
@@ -633,13 +698,19 @@ function renderButton(state, container, options = {}) {
|
|
|
633
698
|
detail: cause === void 0 ? { reason } : { reason, cause }
|
|
634
699
|
}));
|
|
635
700
|
};
|
|
636
|
-
const dispatchRedirected = (url) => {
|
|
637
|
-
|
|
701
|
+
const dispatchRedirected = (url, target) => {
|
|
702
|
+
const detail = { url, target };
|
|
703
|
+
document.dispatchEvent(new CustomEvent("maytes:checkout-redirected", { detail }));
|
|
638
704
|
};
|
|
639
|
-
const
|
|
705
|
+
const navigateAway = (url) => {
|
|
706
|
+
const outcome = navigateTopLevel(url, false);
|
|
640
707
|
teardownActiveCheckout();
|
|
641
|
-
|
|
642
|
-
|
|
708
|
+
if (outcome.target === null) {
|
|
709
|
+
console.error("[maytes/checkout-button] could not leave the embedding frame:", outcome.cause);
|
|
710
|
+
dispatchFailed("navigation-blocked", outcome.cause);
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
dispatchRedirected(url, outcome.target);
|
|
643
714
|
};
|
|
644
715
|
const closeOrphanPopup = (popup) => {
|
|
645
716
|
closePopupWindow(popup);
|
|
@@ -687,9 +758,9 @@ function renderButton(state, container, options = {}) {
|
|
|
687
758
|
navigatePopup(popup, url);
|
|
688
759
|
} else {
|
|
689
760
|
if (shouldUsePopup) {
|
|
690
|
-
console.warn("[maytes/checkout-button] popup was blocked;
|
|
761
|
+
console.warn("[maytes/checkout-button] popup was blocked; redirecting instead");
|
|
691
762
|
}
|
|
692
|
-
|
|
763
|
+
navigateAway(url);
|
|
693
764
|
}
|
|
694
765
|
} catch (err) {
|
|
695
766
|
if (popup !== null && popup.closed) return;
|
|
@@ -738,6 +809,7 @@ function createInstanceState(options, internal) {
|
|
|
738
809
|
config,
|
|
739
810
|
busy: false,
|
|
740
811
|
overlayEl: null,
|
|
812
|
+
overlayDetach: null,
|
|
741
813
|
popupWindow: null,
|
|
742
814
|
popupNavigated: false,
|
|
743
815
|
popupName: generatePopupName(),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/foundation/brand.generated.ts","../src/branding.ts","../src/errors.ts","../src/framing.ts","../src/overlay.ts","../src/env.ts","../src/redirect.ts","../src/version.ts","../src/styles.ts","../src/button.ts","../src/state.ts","../src/maytes.ts"],"sourcesContent":["import { Maytes } from './maytes.js';\n\nif (typeof window !== 'undefined') {\n (window as unknown as { Maytes: typeof Maytes }).Maytes = Maytes;\n}\n\nexport { Maytes };\nexport { MaytesError, MaytesErrorCode } from './errors.js';\nexport type { MaytesErrorCodeValue } from './errors.js';\nexport type {\n CheckoutFailedDetail,\n CheckoutFailedReason,\n CheckoutRedirectedDetail,\n CheckoutUrlOptions,\n CreateCheckoutFn,\n MaytesEnvironment,\n MaytesFactory,\n MaytesInternalOptions,\n MaytesOptions,\n MaytesSDK,\n RedirectOptions,\n RedirectTarget,\n RenderButtonCleanup,\n RenderButtonMode,\n RenderButtonOptions,\n} from './types.js';\nexport { SDK_VERSION } from './version.js';\n","// GENERATED by scripts/sync-foundation-tokens.mjs from kttipay/designsystem v0.3.0 web/tokens.ts — DO NOT EDIT. Refresh: npm run sync:foundation -- --tag vX.Y.Z\n\n// Subset of the foundation used by the checkout button and the mock showcase:\n// brand.primary <- colorsLight.brand.primary (burgundy/600)\n// brand.secondary <- colorsLight.brand.secondary (orange/500)\n// palette.burgundy.700 <- palette.burgundy.700 (hover shade for brand.primary)\n// palette.base.white <- palette.base.white\n// text.primaryInverse <- colorsLight.text.primaryInverse (text on brand.primary)\n\nexport const FOUNDATION_TAG = 'v0.3.0';\n\nexport const foundation = {\n brand: {\n primary: '#4A0324',\n secondary: '#FE572A',\n },\n palette: {\n burgundy: {\n 700: '#3B021D',\n },\n base: {\n white: '#FFFFFF',\n },\n },\n text: {\n primaryInverse: '#FFFFFF',\n },\n} as const;\n","import { foundation } from './foundation/brand.generated.js';\n\nexport const MAYTES_RICHE = foundation.brand.primary;\nexport const MAYTES_WALLET = foundation.brand.secondary;\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\nconst MAYTES_LOGO_PATHS: readonly string[] = [\n 'M392,6.11c-.3-1.61-1.72-2.79-3.38-2.79h-99.97c-1.66,0-3.09,1.19-3.38,2.79l-51.14,275.49c-.36,2.07,1.24,4.03,3.38,4.03h71.07c1.72,0,3.15-1.24,3.38-2.97l5.57-42.24c.23-1.72,1.66-2.97,3.38-2.97h32.45c1.72,0,3.15,1.24,3.38,2.97l5.57,42.24c.23,1.72,1.66,2.97,3.38,2.97h74.46c2.14,0,3.8-1.96,3.38-4.03L392,6.11ZM344.42,174.89h-14.59c-2.07,0-3.62-1.84-3.38-3.86l9.55-74.33c.06-.48.48-.83.95-.83s.89.35.95.83l9.91,74.33c.3,2.02-1.31,3.86-3.38,3.86h0Z',\n 'M218.86,3.32h-77.72c-1.48,0-2.85,1.01-3.27,2.44l-25.63,83.65c-.12.35-.41.6-.83.6s-.71-.23-.83-.6L84.9,5.76c-.41-1.42-1.78-2.44-3.27-2.44H3.44c-1.9,0-3.44,1.54-3.44,3.44v275.43c0,1.9,1.54,3.45,3.44,3.45h71.26c1.9,0,3.44-1.54,3.44-3.45v-77.3l-.83-51.44c0-.53.41-.95.95-.95.41,0,.77.3.89.71l14.42,59.62c.35,1.54,1.72,2.61,3.32,2.61h28.42c1.61,0,2.97-1.06,3.32-2.61l14.47-59.79c.12-.3.35-.53.71-.53.41,0,.71.3.71.71l-.42,51.67-.06.06v77.3c0,1.9,1.54,3.44,3.44,3.44h71.37c1.9,0,3.44-1.54,3.44-3.44V6.77c0-1.9-1.54-3.44-3.44-3.44h0Z',\n 'M1179.6,147c-9.73-11.8-20.71-21.12-47.76-38.44-27.06-16.91-31.69-23.26-31.69-31.68,0-6.76,3.8-11.39,10.56-11.39,8.19,0,14.18,10.44,15.43,26.28.18,2.14,2.13,3.74,4.27,3.26l63.66-14.12c1.6-.36,2.73-1.9,2.61-3.56-3.97-49.3-35-77.36-86.44-77.36-27.47,0-50.25,8.07-67.63,24.09-17.39,16.01-25.82,36.72-25.82,62.53,0,16.91,4.22,32.09,13.12,45.62,8.9,13.53,25.75,28.3,51.56,44.38,14.77,9.32,24.09,16.49,27.88,21.12,4.21,4.63,6.35,9.31,6.35,14.36,0,6.35-4.63,10.56-11.81,10.56-10.5,0-18.15-11.87-19.28-29.66-.12-2.25-2.31-3.91-4.51-3.26l-63.6,18.68c-1.55.42-2.55,1.84-2.43,3.44,1.78,22.84,11.03,41.41,26.88,55.65,16.49,14.36,36.77,21.53,64.24,21.53s50.32-7.59,67.64-23.26c17.74-15.66,26.64-36.37,26.64-61.28,0-22.01-6.35-40.58-19.87-57.49v-.02Z',\n 'M1002.33,3.32h-146.18c-1.9,0-3.44,1.54-3.44,3.44v275.49c0,1.9,1.54,3.44,3.44,3.44h146.18c1.9,0,3.44-1.54,3.44-3.44v-62.05c0-1.9-1.54-3.44-3.44-3.44h-63.3c-1.9,0-3.45-1.54-3.45-3.45v-34.58c0-1.9,1.54-3.44,3.45-3.44v.18h53.63c1.9,0,3.45-1.54,3.45-3.44v-57.84c0-1.9-1.55-3.44-3.45-3.44h-53.63c-1.9,0-3.45-1.54-3.45-3.44v-31.61c0-1.9,1.54-3.44,3.45-3.44h63.3c1.9,0,3.44-1.54,3.44-3.44V6.77c0-1.9-1.54-3.44-3.44-3.44Z',\n 'M840.22,6.77c0-1.9-1.54-3.44-3.44-3.44h-175.31c-1.9,0-3.45,1.54-3.45,3.44v62c0,1.9,1.54,3.44,3.45,3.44h41.77c1.9,0,3.44,1.54,3.44,3.44v206.62c0,1.9,1.54,3.45,3.44,3.45h78.14c1.9,0,3.45-1.54,3.45-3.45V75.7c0-1.9,1.54-3.44,3.45-3.44h41.77c1.9,0,3.44-1.54,3.44-3.44h-.12V6.77h-.02Z',\n 'M607.71,3.38l-.06-.06c-23.23,0-32.59,48.08-40.22,80.25-1.38,5.82-4.74,18.31-7.75,27.31-4.44,13.26-10.68,30.43-22.21,31.93-18.85,2.47-7.14-39.43-7.14-39.43l21.67-92.98c.84-3.6-1.92-7.02-5.58-7.02h-85.49c-3.12,0-5.64,2.46-5.71,5.64l-1.68,75.09c-.48,21.25,5.64,42.31,18.37,59.37,12.72,17.05,38.81,28,63.12,25.9,52.48-7.08,65.46-70.49,68.4-71.1,3.06-.64,2.56,9.3.84,22.15-2.2,16.42-8.46,32.1-18.52,45.27-5.3,6.95-11.13,12.9-16.55,16.37-32.96,22.51-95.69,9.48-122.4-2.7-3.66-1.68-7.75,1.02-7.75,5.04l16.39,83.98c0,.84.18,1.68.54,2.4,9.48,17.83,53.31,19.33,74.43,17.77,32.18-2.04,100.37-29.35,115.32-122.33,12.17-103.08-1.14-162.91-38.06-162.84l.02-.02Z',\n];\n\nexport function buildMaytesLogo(height: string, color: string): SVGSVGElement {\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('xmlns', SVG_NS);\n svg.setAttribute('viewBox', '0 0 1199.47 289.04');\n svg.style.height = height;\n svg.style.width = 'auto';\n svg.style.color = color;\n for (const d of MAYTES_LOGO_PATHS) {\n const path = document.createElementNS(SVG_NS, 'path');\n path.setAttribute('fill', 'currentColor');\n path.setAttribute('d', d);\n svg.appendChild(path);\n }\n return svg;\n}\n","export const MaytesErrorCode = {\n Config: 'CONFIG',\n} as const;\n\nexport type MaytesErrorCodeValue = (typeof MaytesErrorCode)[keyof typeof MaytesErrorCode];\n\nexport class MaytesError extends Error {\n readonly code: MaytesErrorCodeValue;\n\n constructor(code: MaytesErrorCodeValue, message: string) {\n super(message);\n this.code = code;\n this.name = 'MaytesError';\n }\n}\n","import type { RedirectTarget } from './types.js';\n\nexport interface NavigationOutcome {\n target: RedirectTarget | null;\n cause?: unknown;\n}\n\nexport function isSecurityError(err: unknown): boolean {\n return typeof err === 'object' && err !== null && (err as { name?: unknown }).name === 'SecurityError';\n}\n\nexport function isFramed(): boolean {\n return window.top !== null && window.top !== window;\n}\n\nexport function sameOriginTop(): Window | null {\n if (!isFramed()) return null;\n const top = window.top as Window;\n try {\n void top.document;\n return top;\n } catch (err) {\n if (!isSecurityError(err)) throw err;\n return null;\n }\n}\n\nexport function viewportWidth(): number {\n if (!isFramed()) return window.innerWidth;\n const top = sameOriginTop();\n if (top !== null) return top.innerWidth;\n const screenWidth = window.screen?.width;\n return typeof screenWidth === 'number' && screenWidth > 0 ? screenWidth : window.innerWidth;\n}\n\nfunction navigateWindow(target: Window, url: string, replace: boolean): void {\n if (replace) {\n target.location.replace(url);\n } else {\n target.location.href = url;\n }\n}\n\nfunction severOpener(tab: Window): void {\n try {\n tab.opener = null;\n } catch (err) {\n if (!isSecurityError(err)) throw err;\n }\n}\n\nexport function navigateTopLevel(url: string, replace: boolean): NavigationOutcome {\n if (!isFramed()) {\n navigateWindow(window, url, replace);\n return { target: 'self' };\n }\n let refusal: unknown;\n try {\n navigateWindow(window.top as Window, url, replace);\n return { target: 'top' };\n } catch (err) {\n if (!isSecurityError(err)) throw err;\n refusal = err;\n }\n try {\n const tab = window.open(url, '_blank');\n if (tab !== null) {\n severOpener(tab);\n return { target: 'tab' };\n }\n return { target: null, cause: refusal };\n } catch (err) {\n return { target: null, cause: err };\n }\n}\n","import { buildMaytesLogo, MAYTES_WALLET } from './branding.js';\nimport { isSecurityError, sameOriginTop } from './framing.js';\nimport type { InstanceState } from './state.js';\n\nconst TITLE_ID = 'maytes-overlay-title';\nconst STYLE_MARKER = 'data-maytes-checkout-button-overlay-styles';\nconst NATIVE_BACKDROP_FALLBACK = 'rgba(0, 0, 0, 0.6)';\n\nfunction tryReadTopDocument(): Document | null {\n const top = sameOriginTop();\n if (top === null) return null;\n const topDoc = top.document;\n return topDoc.body !== null ? topDoc : null;\n}\n\nfunction resolveOverlayHost(): Document {\n return tryReadTopDocument() ?? document;\n}\n\nfunction ensureOverlayStylesInTopDocument(host: Document): void {\n if (host === document) return;\n if (host.querySelector(`style[${STYLE_MARKER}]`) !== null) return;\n const localStyle = document.head.querySelector('style[data-maytes-checkout-button]');\n if (localStyle === null) return;\n const copy = host.createElement('style');\n copy.setAttribute(STYLE_MARKER, '');\n const nonce = localStyle.getAttribute('nonce');\n if (nonce !== null) copy.setAttribute('nonce', nonce);\n copy.textContent = localStyle.textContent ?? '';\n host.head.appendChild(copy);\n}\n\nfunction buildOverlay(host: Document, state: InstanceState): HTMLDialogElement {\n const dialog = host.createElement('dialog');\n dialog.className = 'maytes-checkout-overlay';\n dialog.setAttribute('aria-labelledby', TITLE_ID);\n dialog.setAttribute('data-maytes-overlay', '');\n\n const content = host.createElement('div');\n content.className = 'maytes-checkout-overlay__content';\n\n const logoDiv = host.createElement('div');\n logoDiv.setAttribute('aria-hidden', 'true');\n logoDiv.appendChild(buildMaytesLogo('2.5rem', MAYTES_WALLET));\n content.appendChild(logoDiv);\n\n const spinner = host.createElement('div');\n spinner.className = 'maytes-checkout-overlay__spinner';\n spinner.setAttribute('role', 'status');\n spinner.setAttribute('aria-live', 'polite');\n spinner.setAttribute('aria-label', 'Checkout in progress');\n content.appendChild(spinner);\n\n const text = host.createElement('p');\n text.id = TITLE_ID;\n text.className = 'maytes-checkout-overlay__text';\n text.textContent = 'Completing checkout with Maytes…';\n content.appendChild(text);\n\n const link = host.createElement('button');\n link.className = 'maytes-checkout-overlay__link';\n link.type = 'button';\n link.textContent = 'Return to Maytes';\n link.addEventListener('click', () => {\n if (state.popupWindow !== null && !state.popupWindow.closed) {\n try { state.popupWindow.focus(); } catch (err) {\n if (!isSecurityError(err)) throw err;\n }\n }\n });\n content.appendChild(link);\n\n dialog.appendChild(content);\n\n dialog.addEventListener('cancel', (event) => {\n event.preventDefault();\n if (state.popupWindow !== null && !state.popupWindow.closed) state.popupWindow.close();\n hideOverlay(state);\n });\n\n return dialog;\n}\n\nfunction applyNativeBackdropFallback(dialog: HTMLDialogElement): void {\n dialog.style.background = NATIVE_BACKDROP_FALLBACK;\n}\n\nexport function showOverlay(state: InstanceState): void {\n if (state.overlayEl !== null) return;\n const host = resolveOverlayHost();\n ensureOverlayStylesInTopDocument(host);\n const dialog = buildOverlay(host, state);\n state.overlayEl = dialog;\n host.body.appendChild(dialog);\n if (host !== document) detachOverlayWhenThisPageHides(state);\n if (typeof dialog.showModal === 'function') {\n try {\n dialog.showModal();\n } catch (err) {\n console.warn('[maytes/checkout-button] dialog.showModal failed; falling back to inline backdrop', err);\n dialog.setAttribute('open', '');\n applyNativeBackdropFallback(dialog);\n }\n } else {\n dialog.setAttribute('open', '');\n applyNativeBackdropFallback(dialog);\n }\n}\n\nfunction detachOverlayWhenThisPageHides(state: InstanceState): void {\n const onPageHide = () => hideOverlay(state);\n window.addEventListener('pagehide', onPageHide);\n state.overlayDetach = () => window.removeEventListener('pagehide', onPageHide);\n}\n\nexport function hideOverlay(state: InstanceState): void {\n if (state.overlayEl === null) return;\n state.overlayDetach?.();\n state.overlayDetach = null;\n const dialog = state.overlayEl;\n const host = dialog.ownerDocument;\n if (typeof dialog.close === 'function' && dialog.open) dialog.close();\n dialog.remove();\n if (host !== document) {\n host.head.querySelector(`style[${STYLE_MARKER}]`)?.remove();\n }\n state.overlayEl = null;\n}\n","import { MaytesError, MaytesErrorCode } from './errors.js';\nimport type { MaytesEnvironment } from './types.js';\n\nexport type InternalEnvironment = MaytesEnvironment | 'staging';\n\nconst ENVIRONMENT_BASE_URLS: Record<InternalEnvironment, string> = {\n staging: 'https://staging-checkout.maytes.co',\n sandbox: 'https://sandbox-checkout.maytes.co',\n production: 'https://checkout.maytes.co',\n};\n\nexport function isValidEnvironment(value: unknown): value is InternalEnvironment {\n return value === 'sandbox' || value === 'production' || value === 'staging';\n}\n\nexport function resolveBaseUrl(environment: InternalEnvironment, override: string | undefined): string {\n if (override !== undefined) return override;\n const url = ENVIRONMENT_BASE_URLS[environment];\n if (url === undefined) {\n throw new MaytesError(MaytesErrorCode.Config, `Unknown environment: ${String(environment)}`);\n }\n return url;\n}\n","import { MaytesError, MaytesErrorCode } from './errors.js';\nimport { resolveBaseUrl, type InternalEnvironment } from './env.js';\nimport { navigateTopLevel } from './framing.js';\nimport type { CheckoutUrlOptions, RedirectOptions } from './types.js';\n\nexport function isHttpUrl(value: string): boolean {\n let parsed: URL;\n try {\n parsed = new URL(value);\n } catch {\n return false;\n }\n return parsed.protocol === 'https:' || parsed.protocol === 'http:';\n}\n\nexport function normalizeBaseUrl(rawBaseUrl: string): string {\n const candidate = rawBaseUrl.trim().replace(/\\/+$/, '');\n let parsed: URL;\n try {\n parsed = new URL(candidate);\n } catch {\n throw new MaytesError(MaytesErrorCode.Config, `baseUrl is not a valid URL: ${candidate}`);\n }\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n throw new MaytesError(\n MaytesErrorCode.Config,\n `baseUrl must use http or https; got ${parsed.protocol}`,\n );\n }\n return candidate;\n}\n\nfunction requireCheckoutId(id: unknown): string {\n if (typeof id !== 'string' || id.trim().length === 0) {\n throw new MaytesError(MaytesErrorCode.Config, 'checkoutId is required (non-empty string)');\n }\n return id.trim();\n}\n\nexport function buildCheckoutUrl(\n environment: InternalEnvironment,\n baseUrlOverride: string | undefined,\n checkoutId: string,\n): string {\n const id = requireCheckoutId(checkoutId);\n const base = normalizeBaseUrl(resolveBaseUrl(environment, baseUrlOverride));\n return `${base}/?id=${encodeURIComponent(id)}`;\n}\n\nexport function performRedirect(url: string, replace: boolean): void {\n if (typeof window === 'undefined') {\n throw new MaytesError(\n MaytesErrorCode.Config,\n 'redirectToCheckout requires a browser context (window is undefined)',\n );\n }\n const outcome = navigateTopLevel(url, replace);\n if (outcome.target === null) {\n throw new MaytesError(\n MaytesErrorCode.Config,\n 'redirectToCheckout could not leave the embedding iframe; call it from a user gesture or from the top-level page',\n );\n }\n}\n\nexport function makeRedirect(\n environment: InternalEnvironment,\n baseUrlOverride: string | undefined,\n) {\n return {\n checkoutUrl(opts: CheckoutUrlOptions): string {\n return buildCheckoutUrl(environment, baseUrlOverride, opts.checkoutId);\n },\n redirectToCheckout(opts: RedirectOptions): void {\n const url = buildCheckoutUrl(environment, baseUrlOverride, opts.checkoutId);\n performRedirect(url, opts.replace === true);\n },\n };\n}\n","export const SDK_VERSION = '1.1.1';\n","import { foundation } from './foundation/brand.generated.js';\nimport { SDK_VERSION } from './version.js';\n\nconst STYLE_ATTR = 'data-maytes-checkout-button';\nconst STYLE_SELECTOR = `style[${STYLE_ATTR}=\"${SDK_VERSION}\"]`;\nconst REFCOUNT_KEY = `__maytes_checkout_button_styles_refs_${SDK_VERSION}__`;\n\ninterface RefCountWindow extends Window {\n [REFCOUNT_KEY]?: number;\n}\n\n// WEB-LOCAL: no foundation role (a11y focus ring); see MOB-994\nconst FOCUS_RING = '#6b8aff';\n\nconst BUTTON_CSS = `\n.maytes-checkout-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.57em;\n padding: 0.71em 1.29em;\n border: none;\n border-radius: 999px;\n background: ${foundation.brand.primary};\n color: ${foundation.text.primaryInverse};\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n font-size: var(--maytes-button-font-size, 14px);\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n user-select: none;\n transition: background-color 120ms ease, opacity 120ms ease;\n}\n.maytes-checkout-button:hover { background: ${foundation.palette.burgundy[700]}; }\n.maytes-checkout-button:focus-visible {\n outline: 2px solid ${FOCUS_RING};\n outline-offset: 2px;\n}\n.maytes-checkout-button[aria-disabled='true'] {\n cursor: progress;\n opacity: 0.7;\n}\n.maytes-checkout-button--block {\n display: flex;\n width: 100%;\n}\n.maytes-checkout-button__logo { height: 1em; width: auto; flex: none; }\n.maytes-checkout-button__spinner {\n height: 1em;\n width: 1em;\n border-radius: 50%;\n border: 0.14em solid currentColor;\n border-right-color: transparent;\n animation: maytes-checkout-button-spin 0.7s linear infinite;\n}\n@keyframes maytes-checkout-button-spin {\n to { transform: rotate(360deg); }\n}\n.maytes-checkout-overlay {\n position: fixed;\n inset: 0;\n width: 100vw;\n height: 100vh;\n max-width: 100vw;\n max-height: 100vh;\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n z-index: 2147483646;\n font: 500 15px/1.4 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n}\n.maytes-checkout-overlay[open] {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.maytes-checkout-overlay::backdrop {\n background: rgba(0, 0, 0, 0.6);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n}\n.maytes-checkout-overlay__content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1.5rem;\n}\n.maytes-checkout-overlay__spinner {\n width: 2.5rem;\n height: 2.5rem;\n border: 4px solid rgba(255, 255, 255, 0.3);\n border-top-color: ${foundation.brand.secondary};\n border-radius: 50%;\n animation: maytes-checkout-button-spin 0.8s linear infinite;\n}\n.maytes-checkout-overlay__text {\n color: ${foundation.text.primaryInverse};\n font-size: 1.125rem;\n font-weight: 500;\n margin: 0;\n}\n.maytes-checkout-overlay__link {\n color: rgba(255, 255, 255, 0.7);\n font-size: 0.875rem;\n text-decoration: underline;\n text-underline-offset: 4px;\n background: none;\n border: none;\n cursor: pointer;\n font-family: inherit;\n transition: color 0.15s;\n}\n.maytes-checkout-overlay__link:hover { color: ${foundation.text.primaryInverse}; }\n@media (prefers-reduced-motion: reduce) {\n .maytes-checkout-overlay__spinner,\n .maytes-checkout-button__spinner { animation: none; }\n}\n`;\n\nexport const POPUP_LOADING_CSS = `\n:root { color-scheme: light; }\nhtml, body { margin: 0; height: 100%; }\nbody.maytes-popup-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n background: ${foundation.brand.primary};\n color: ${foundation.text.primaryInverse};\n font: 500 16px/1.45 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n}\n.maytes-popup-loading__content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1.5rem;\n padding: 2rem;\n text-align: center;\n}\n.maytes-popup-loading__logo { height: 2.75rem; width: auto; }\n.maytes-popup-loading__spinner {\n width: 2.5rem;\n height: 2.5rem;\n border: 4px solid rgba(255, 255, 255, 0.25);\n border-top-color: ${foundation.brand.secondary};\n border-radius: 50%;\n animation: maytes-checkout-button-spin 0.8s linear infinite;\n}\n@keyframes maytes-checkout-button-spin {\n to { transform: rotate(360deg); }\n}\n.maytes-popup-loading__text { margin: 0; font-size: 1.05rem; font-weight: 500; }\n.maytes-popup-loading__slow {\n margin: 0;\n font-size: 0.9rem;\n font-weight: 400;\n color: rgba(255, 255, 255, 0.75);\n max-width: 22rem;\n}\n.maytes-popup-loading__slow[hidden] { display: none; }\n@media (prefers-reduced-motion: reduce) {\n .maytes-popup-loading__spinner { animation: none; }\n}\n`;\n\nfunction getRefCount(): number {\n const w = window as RefCountWindow;\n return w[REFCOUNT_KEY] ?? 0;\n}\n\nfunction setRefCount(value: number): void {\n const w = window as RefCountWindow;\n w[REFCOUNT_KEY] = value;\n}\n\nexport function ensureStylesInjected(cspNonce: string | undefined): void {\n const next = getRefCount() + 1;\n setRefCount(next);\n if (document.head.querySelector(STYLE_SELECTOR) !== null) return;\n const el = document.createElement('style');\n el.setAttribute(STYLE_ATTR, SDK_VERSION);\n if (cspNonce !== undefined && cspNonce !== '') el.setAttribute('nonce', cspNonce);\n el.textContent = BUTTON_CSS;\n document.head.appendChild(el);\n}\n\nexport function releaseStyles(): void {\n const next = Math.max(0, getRefCount() - 1);\n setRefCount(next);\n if (next > 0) return;\n const el = document.head.querySelector(STYLE_SELECTOR);\n if (el !== null) el.remove();\n}\n\nexport function resetStylesForTests(): void {\n setRefCount(0);\n document.head.querySelectorAll(`style[${STYLE_ATTR}]`).forEach((el) => el.remove());\n}\n","import { buildMaytesLogo } from './branding.js';\nimport { foundation } from './foundation/brand.generated.js';\nimport { MaytesError, MaytesErrorCode } from './errors.js';\nimport { isSecurityError, navigateTopLevel, viewportWidth } from './framing.js';\nimport { hideOverlay, showOverlay } from './overlay.js';\nimport { buildCheckoutUrl, isHttpUrl } from './redirect.js';\nimport { ensureStylesInjected, POPUP_LOADING_CSS, releaseStyles } from './styles.js';\nimport type { InstanceState } from './state.js';\nimport type {\n CheckoutFailedReason,\n CheckoutRedirectedDetail,\n RedirectTarget,\n RenderButtonCleanup,\n RenderButtonMode,\n RenderButtonOptions,\n} from './types.js';\n\nconst POPUP_WIDTH = 500;\nconst POPUP_HEIGHT = 800;\nconst POPUP_POLL_INTERVAL_MS = 500;\nconst MOBILE_MAX_WIDTH = 600;\nconst SLOW_NETWORK_DELAY_MS = 8000;\n\nfunction buildLogo(): SVGSVGElement {\n const svg = buildMaytesLogo('1em', 'currentColor');\n svg.setAttribute('class', 'maytes-checkout-button__logo');\n svg.setAttribute('aria-hidden', 'true');\n return svg;\n}\n\nfunction buildSpinner(): HTMLSpanElement {\n const spinner = document.createElement('span');\n spinner.className = 'maytes-checkout-button__spinner';\n spinner.setAttribute('aria-hidden', 'true');\n return spinner;\n}\n\nfunction isValidCheckoutResult(value: unknown): value is { checkoutId: string; checkoutUrl?: string } {\n if (typeof value !== 'object' || value === null) return false;\n const obj = value as { checkoutId?: unknown; checkoutUrl?: unknown };\n if (typeof obj.checkoutId !== 'string' || obj.checkoutId.trim().length === 0) return false;\n if (obj.checkoutUrl !== undefined) {\n if (typeof obj.checkoutUrl !== 'string' || obj.checkoutUrl.trim().length === 0) return false;\n if (!isHttpUrl(obj.checkoutUrl)) return false;\n }\n return true;\n}\n\nfunction refocusPopup(popup: Window): void {\n try { popup.focus(); } catch (err) {\n if (!isSecurityError(err)) throw err;\n }\n}\n\nexport function closePopupWindow(popup: Window | null): void {\n if (popup === null) return;\n try {\n if (!popup.closed) popup.close();\n } catch (err) {\n if (!isSecurityError(err)) throw err;\n }\n}\n\nfunction popupFeatures(): string {\n const screenWidth = window.screen?.width ?? POPUP_WIDTH;\n const screenHeight = window.screen?.height ?? POPUP_HEIGHT;\n const left = Math.max(0, Math.round((screenWidth - POPUP_WIDTH) / 2));\n const top = Math.max(0, Math.round((screenHeight - POPUP_HEIGHT) / 2));\n return `popup=yes,width=${POPUP_WIDTH},height=${POPUP_HEIGHT},left=${left},top=${top},resizable=yes,scrollbars=yes`;\n}\n\nexport function stopPopupPoll(state: InstanceState): void {\n if (state.popupPollHandle !== null) {\n clearInterval(state.popupPollHandle);\n state.popupPollHandle = null;\n }\n}\n\nfunction startPopupPoll(state: InstanceState, onClose: () => void): void {\n stopPopupPoll(state);\n state.popupPollHandle = setInterval(() => {\n const popup = state.popupWindow;\n if (popup === null || popup.closed) {\n stopPopupPoll(state);\n state.popupWindow = null;\n onClose();\n }\n }, POPUP_POLL_INTERVAL_MS);\n}\n\nfunction isMobileViewport(): boolean {\n return viewportWidth() <= MOBILE_MAX_WIDTH;\n}\n\nfunction openBlankPopup(state: InstanceState): Window | null {\n return window.open('about:blank', state.popupName, popupFeatures());\n}\n\nfunction navigatePopup(popup: Window, url: string): void {\n popup.location.replace(url);\n}\n\nfunction removePopupChildren(doc: Document): void {\n while (doc.body.firstChild !== null) doc.body.removeChild(doc.body.firstChild);\n}\n\nfunction paintPopupLoadingScreen(popup: Window, cspNonce: string | undefined): void {\n const doc = popup.document as Document | null;\n if (doc === null || doc.head === null || doc.body === null) return;\n doc.title = 'Maytes checkout';\n doc.documentElement.lang = 'en';\n const style = doc.createElement('style');\n if (cspNonce !== undefined && cspNonce !== '') style.setAttribute('nonce', cspNonce);\n style.textContent = POPUP_LOADING_CSS;\n doc.head.appendChild(style);\n\n doc.body.classList.add('maytes-popup-loading');\n removePopupChildren(doc);\n\n const content = doc.createElement('main');\n content.className = 'maytes-popup-loading__content';\n content.setAttribute('role', 'status');\n content.setAttribute('aria-live', 'polite');\n\n const logo = buildMaytesLogo('2.75rem', foundation.text.primaryInverse);\n logo.setAttribute('class', 'maytes-popup-loading__logo');\n logo.setAttribute('aria-hidden', 'true');\n content.appendChild(logo);\n\n const spinner = doc.createElement('div');\n spinner.className = 'maytes-popup-loading__spinner';\n spinner.setAttribute('aria-hidden', 'true');\n content.appendChild(spinner);\n\n const text = doc.createElement('p');\n text.className = 'maytes-popup-loading__text';\n text.textContent = 'Completing checkout with Maytes…';\n content.appendChild(text);\n\n const slow = doc.createElement('p');\n slow.className = 'maytes-popup-loading__slow';\n slow.hidden = true;\n slow.textContent = 'Still connecting. This can take a moment on slow networks.';\n content.appendChild(slow);\n\n doc.body.appendChild(content);\n setTimeout(() => { slow.hidden = false; }, SLOW_NETWORK_DELAY_MS);\n}\n\nexport function renderButton(\n state: InstanceState,\n container: HTMLElement,\n options: RenderButtonOptions = {},\n): RenderButtonCleanup {\n if (state.destroyed) {\n throw new MaytesError(\n MaytesErrorCode.Config,\n 'renderButton() called on a destroyed Maytes instance',\n );\n }\n if (!(container instanceof HTMLElement)) {\n throw new MaytesError(MaytesErrorCode.Config, 'renderButton(container) requires an HTMLElement');\n }\n\n ensureStylesInjected(state.config.cspNonce);\n\n const label = options.label ?? 'Split with';\n const block = options.block === true;\n const mode: RenderButtonMode = options.mode ?? 'popup';\n if (mode !== 'redirect' && mode !== 'popup') {\n throw new MaytesError(\n MaytesErrorCode.Config,\n \"renderButton({ mode }) must be 'redirect' or 'popup'\",\n );\n }\n\n const button = document.createElement('button');\n button.type = 'button';\n button.className = block\n ? 'maytes-checkout-button maytes-checkout-button--block'\n : 'maytes-checkout-button';\n button.setAttribute('aria-label', `${label} Maytes`);\n\n const labelNode = document.createTextNode(`${label} `);\n const logo = buildLogo();\n button.appendChild(labelNode);\n button.appendChild(logo);\n\n const setBusy = (busy: boolean) => {\n state.busy = busy;\n if (busy) {\n button.setAttribute('aria-disabled', 'true');\n button.setAttribute('aria-busy', 'true');\n logo.replaceWith(buildSpinner());\n } else {\n button.removeAttribute('aria-disabled');\n button.removeAttribute('aria-busy');\n const currentIndicator = button.querySelector('.maytes-checkout-button__spinner, .maytes-checkout-button__logo');\n if (currentIndicator !== null) currentIndicator.replaceWith(buildLogo());\n }\n };\n\n const teardownActiveCheckout = () => {\n hideOverlay(state);\n setBusy(false);\n };\n\n const onPopupClosed = () => {\n teardownActiveCheckout();\n document.dispatchEvent(new CustomEvent('maytes:checkout-closed'));\n };\n\n const dispatchFailed = (reason: CheckoutFailedReason, cause?: unknown): void => {\n document.dispatchEvent(new CustomEvent('maytes:checkout-failed', {\n detail: cause === undefined ? { reason } : { reason, cause },\n }));\n };\n\n const dispatchRedirected = (url: string, target: RedirectTarget): void => {\n const detail: CheckoutRedirectedDetail = { url, target };\n document.dispatchEvent(new CustomEvent('maytes:checkout-redirected', { detail }));\n };\n\n const navigateAway = (url: string): void => {\n const outcome = navigateTopLevel(url, false);\n teardownActiveCheckout();\n if (outcome.target === null) {\n console.error('[maytes/checkout-button] could not leave the embedding frame:', outcome.cause);\n dispatchFailed('navigation-blocked', outcome.cause);\n return;\n }\n dispatchRedirected(url, outcome.target);\n };\n\n const closeOrphanPopup = (popup: Window | null): void => {\n closePopupWindow(popup);\n stopPopupPoll(state);\n if (state.popupWindow === popup) state.popupWindow = null;\n teardownActiveCheckout();\n };\n\n const handleClick = async (): Promise<void> => {\n if (state.busy || state.destroyed) return;\n setBusy(true);\n const shouldUsePopup = mode === 'popup' && !isMobileViewport();\n const popup = shouldUsePopup ? openBlankPopup(state) : null;\n if (popup !== null) {\n state.popupWindow = popup;\n state.popupNavigated = false;\n refocusPopup(popup);\n paintPopupLoadingScreen(popup, state.config.cspNonce);\n showOverlay(state);\n document.dispatchEvent(new CustomEvent('maytes:checkout-opened'));\n startPopupPoll(state, onPopupClosed);\n }\n try {\n const result = await state.config.createCheckout();\n if (state.destroyed || (popup !== null && popup.closed)) {\n closePopupWindow(popup);\n return;\n }\n if (!isValidCheckoutResult(result)) {\n closeOrphanPopup(popup);\n const shapeError = new MaytesError(\n MaytesErrorCode.Config,\n 'createCheckout must resolve to { checkoutId: string, checkoutUrl?: http(s) URL }',\n );\n console.error(shapeError);\n dispatchFailed('invalid-shape', shapeError);\n return;\n }\n const url = result.checkoutUrl ?? buildCheckoutUrl(\n state.config.environment,\n state.config.baseUrl,\n result.checkoutId,\n );\n if (popup !== null) {\n state.popupNavigated = true;\n navigatePopup(popup, url);\n } else {\n if (shouldUsePopup) {\n console.warn('[maytes/checkout-button] popup was blocked; redirecting instead');\n }\n navigateAway(url);\n }\n } catch (err) {\n if (popup !== null && popup.closed) return;\n closeOrphanPopup(popup);\n console.error('[maytes/checkout-button] createCheckout failed:', err);\n dispatchFailed('create-checkout-rejected', err);\n }\n };\n\n button.addEventListener('click', handleClick);\n container.appendChild(button);\n\n let cleaned = false;\n const teardown = (): void => {\n if (cleaned) return;\n cleaned = true;\n button.removeEventListener('click', handleClick);\n button.remove();\n state.teardowns.delete(teardown);\n releaseStyles();\n };\n state.teardowns.add(teardown);\n\n return teardown;\n}\n","import type { MaytesOptions, MaytesInternalOptions } from './types.js';\n\nexport interface InstanceState {\n config: MaytesOptions & MaytesInternalOptions;\n busy: boolean;\n overlayEl: HTMLDialogElement | null;\n overlayDetach: (() => void) | null;\n popupWindow: Window | null;\n popupNavigated: boolean;\n popupName: string;\n popupPollHandle: ReturnType<typeof setInterval> | null;\n destroyed: boolean;\n teardowns: Set<() => void>;\n}\n\nfunction popupNameSuffix(): string {\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\nfunction generatePopupName(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n try {\n return `maytes-checkout-${crypto.randomUUID()}`;\n } catch {\n return `maytes-checkout-${popupNameSuffix()}`;\n }\n }\n return `maytes-checkout-${popupNameSuffix()}`;\n}\n\nexport function createInstanceState(\n options: MaytesOptions,\n internal: MaytesInternalOptions | undefined,\n): InstanceState {\n const config: MaytesOptions & MaytesInternalOptions = {\n createCheckout: options.createCheckout,\n environment: options.environment,\n };\n if (internal?.baseUrl !== undefined) config.baseUrl = internal.baseUrl;\n if (internal?.cspNonce !== undefined) config.cspNonce = internal.cspNonce;\n return {\n config,\n busy: false,\n overlayEl: null,\n overlayDetach: null,\n popupWindow: null,\n popupNavigated: false,\n popupName: generatePopupName(),\n popupPollHandle: null,\n destroyed: false,\n teardowns: new Set(),\n };\n}\n","import { closePopupWindow, renderButton, stopPopupPoll } from './button.js';\nimport { isValidEnvironment } from './env.js';\nimport { MaytesError, MaytesErrorCode } from './errors.js';\nimport { hideOverlay } from './overlay.js';\nimport { makeRedirect, normalizeBaseUrl } from './redirect.js';\nimport { createInstanceState } from './state.js';\nimport type {\n MaytesFactory,\n MaytesInternalOptions,\n MaytesOptions,\n MaytesSDK,\n} from './types.js';\n\nfunction validateOptions(options: MaytesOptions): void {\n if (typeof options !== 'object' || options === null) {\n throw new MaytesError(MaytesErrorCode.Config, 'Maytes() requires an options object');\n }\n if (typeof options.createCheckout !== 'function') {\n throw new MaytesError(\n MaytesErrorCode.Config,\n 'Maytes({ createCheckout }) must be an async function returning { checkoutId }',\n );\n }\n if (!isValidEnvironment(options.environment)) {\n throw new MaytesError(\n MaytesErrorCode.Config,\n \"Maytes({ environment }) must be 'sandbox' or 'production'\",\n );\n }\n}\n\nfunction validateInternalOptions(internal: MaytesInternalOptions | undefined): void {\n if (internal === undefined) return;\n if (internal.baseUrl !== undefined) normalizeBaseUrl(internal.baseUrl);\n}\n\nexport const Maytes: MaytesFactory = (options, internal) => {\n validateOptions(options);\n validateInternalOptions(internal);\n\n const state = createInstanceState(options, internal);\n const { checkoutUrl, redirectToCheckout } = makeRedirect(\n state.config.environment,\n state.config.baseUrl,\n );\n\n const sdk: MaytesSDK = {\n renderButton(container, opts) {\n return renderButton(state, container, opts);\n },\n redirectToCheckout(opts) {\n redirectToCheckout(opts);\n },\n checkoutUrl(opts) {\n return checkoutUrl(opts);\n },\n destroy() {\n if (state.destroyed) return;\n state.destroyed = true;\n stopPopupPoll(state);\n hideOverlay(state);\n if (!state.popupNavigated) closePopupWindow(state.popupWindow);\n state.popupWindow = null;\n state.busy = false;\n for (const teardown of [...state.teardowns]) teardown();\n state.teardowns.clear();\n },\n };\n\n return sdk;\n};\n"],"mappings":"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","names":[]}
|