@jupiterdo/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/api.d.ts +13 -0
- package/dist/constants.d.ts +16 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.esm.js +604 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.umd.js +613 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/index.umd.min.js +2 -0
- package/dist/index.umd.min.js.map +1 -0
- package/dist/jupiter.d.ts +40 -0
- package/dist/modal.d.ts +22 -0
- package/dist/types.d.ts +56 -0
- package/package.json +32 -0
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Jupiter = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
|
+
|
|
7
|
+
/******************************************************************************
|
|
8
|
+
Copyright (c) Microsoft Corporation.
|
|
9
|
+
|
|
10
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
11
|
+
purpose with or without fee is hereby granted.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
14
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
15
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
16
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
17
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
18
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
19
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
20
|
+
***************************************************************************** */
|
|
21
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
25
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
26
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
27
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
28
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
29
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
30
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
35
|
+
var e = new Error(message);
|
|
36
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* API base URLs for different environments
|
|
41
|
+
*/
|
|
42
|
+
const API_URLS = {
|
|
43
|
+
production: "https://api.jupiter.do",
|
|
44
|
+
sandbox: "https://api-sandbox.jupiter.do",
|
|
45
|
+
localhost: "http://localhost:8000",
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* App URLs for different environments
|
|
49
|
+
*/
|
|
50
|
+
const APP_URLS = {
|
|
51
|
+
production: "https://jupiter.do",
|
|
52
|
+
sandbox: "https://sandbox.jupiter.do",
|
|
53
|
+
localhost: "http://localhost:3000",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* API client for communicating with Jupiter backend
|
|
58
|
+
*/
|
|
59
|
+
class JupiterAPI {
|
|
60
|
+
constructor(config) {
|
|
61
|
+
this.apiKey = config.apiKey;
|
|
62
|
+
this.baseUrl = API_URLS[config.environment || "production"];
|
|
63
|
+
}
|
|
64
|
+
createPaymentLink(amount, referenceId) {
|
|
65
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
var _a;
|
|
67
|
+
let response;
|
|
68
|
+
try {
|
|
69
|
+
response = yield fetch(`${this.baseUrl}/sdk/link/`, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: {
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
amount,
|
|
77
|
+
reference_id: referenceId,
|
|
78
|
+
}),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
// Handle network errors
|
|
83
|
+
throw {
|
|
84
|
+
code: "NETWORK_ERROR",
|
|
85
|
+
message: error instanceof Error ? error.message : "Unknown error",
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
const error = yield response.json().catch(() => ({}));
|
|
90
|
+
throw {
|
|
91
|
+
code: error.code || `HTTP_${response.status}`,
|
|
92
|
+
message: error.detail ||
|
|
93
|
+
((_a = error.amount) === null || _a === void 0 ? void 0 : _a[0]) ||
|
|
94
|
+
`API error: ${response.status} ${response.statusText}`,
|
|
95
|
+
details: error,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return response.json();
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const MODAL_STYLES = `
|
|
104
|
+
/* Animations */
|
|
105
|
+
@keyframes jupiter-fadeIn {
|
|
106
|
+
from { opacity: 0; }
|
|
107
|
+
to { opacity: 1; }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@keyframes jupiter-fadeOut {
|
|
111
|
+
from { opacity: 1; }
|
|
112
|
+
to { opacity: 0; }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@keyframes jupiter-fadeInZoom {
|
|
116
|
+
from {
|
|
117
|
+
opacity: 0;
|
|
118
|
+
transform: translate(-50%, -50%) scale(0.95);
|
|
119
|
+
}
|
|
120
|
+
to {
|
|
121
|
+
opacity: 1;
|
|
122
|
+
transform: translate(-50%, -50%) scale(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@keyframes jupiter-fadeOutZoom {
|
|
127
|
+
from {
|
|
128
|
+
opacity: 1;
|
|
129
|
+
transform: translate(-50%, -50%) scale(1);
|
|
130
|
+
}
|
|
131
|
+
to {
|
|
132
|
+
opacity: 0;
|
|
133
|
+
transform: translate(-50%, -50%) scale(0.95);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@keyframes jupiter-slideInFromRight {
|
|
138
|
+
from { transform: translateX(100%); }
|
|
139
|
+
to { transform: translateX(0); }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@keyframes jupiter-slideOutToRight {
|
|
143
|
+
from { transform: translateX(0); }
|
|
144
|
+
to { transform: translateX(100%); }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Overlay */
|
|
148
|
+
.jupiter-modal-overlay {
|
|
149
|
+
position: fixed;
|
|
150
|
+
inset: 0;
|
|
151
|
+
z-index: 9999;
|
|
152
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
153
|
+
display: none;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.jupiter-modal-overlay.open {
|
|
157
|
+
display: block;
|
|
158
|
+
animation: jupiter-fadeIn 0.2s ease-out;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.jupiter-modal-overlay.closing {
|
|
162
|
+
animation: jupiter-fadeOut 0.2s ease-out;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Container */
|
|
166
|
+
.jupiter-modal-container {
|
|
167
|
+
display: none;
|
|
168
|
+
position: relative;
|
|
169
|
+
border-radius: 0.625rem;
|
|
170
|
+
overflow: hidden;
|
|
171
|
+
background-color: oklch(0.145 0 0);
|
|
172
|
+
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.jupiter-modal-container.open {
|
|
176
|
+
display: flex;
|
|
177
|
+
flex-direction: column;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* Container - Mobile */
|
|
181
|
+
@media (max-width: 767px) {
|
|
182
|
+
.jupiter-modal-container {
|
|
183
|
+
border-radius: 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.jupiter-modal-container.open {
|
|
187
|
+
position: fixed;
|
|
188
|
+
inset: 0;
|
|
189
|
+
z-index: 10000;
|
|
190
|
+
animation: jupiter-slideInFromRight 0.5s ease-out;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.jupiter-modal-container.closing {
|
|
194
|
+
animation: jupiter-slideOutToRight 0.3s ease-out;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.jupiter-modal-overlay {
|
|
198
|
+
pointer-events: none;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Container - Desktop */
|
|
203
|
+
@media (min-width: 768px) {
|
|
204
|
+
.jupiter-modal-container.open {
|
|
205
|
+
position: fixed;
|
|
206
|
+
top: 50%;
|
|
207
|
+
left: 50%;
|
|
208
|
+
transform: translate(-50%, -50%);
|
|
209
|
+
z-index: 10000;
|
|
210
|
+
width: calc(100% - 2rem);
|
|
211
|
+
max-width: 440px;
|
|
212
|
+
max-height: calc(100vh - 4rem);
|
|
213
|
+
padding: 18px;
|
|
214
|
+
animation: jupiter-fadeInZoom 0.2s ease-out;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.jupiter-modal-container.closing {
|
|
218
|
+
animation: jupiter-fadeOutZoom 0.2s ease-out;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* Close Button */
|
|
223
|
+
.jupiter-modal-close {
|
|
224
|
+
position: absolute;
|
|
225
|
+
top: 8px;
|
|
226
|
+
right: 8px;
|
|
227
|
+
background: transparent;
|
|
228
|
+
border: none;
|
|
229
|
+
cursor: pointer;
|
|
230
|
+
opacity: 0.7;
|
|
231
|
+
transition: opacity 0.2s;
|
|
232
|
+
padding: 0.25rem;
|
|
233
|
+
border-radius: 0.25rem;
|
|
234
|
+
display: flex;
|
|
235
|
+
align-items: center;
|
|
236
|
+
justify-content: center;
|
|
237
|
+
z-index: 10001;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.jupiter-modal-close:hover {
|
|
241
|
+
opacity: 1;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* Iframe - Mobile */
|
|
245
|
+
@media (max-width: 767px) {
|
|
246
|
+
.jupiter-modal-iframe {
|
|
247
|
+
width: 100%;
|
|
248
|
+
height: 100%;
|
|
249
|
+
flex: 1;
|
|
250
|
+
border: none;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Iframe - Desktop */
|
|
255
|
+
@media (min-width: 768px) {
|
|
256
|
+
.jupiter-modal-iframe {
|
|
257
|
+
width: 100%;
|
|
258
|
+
height: 600px;
|
|
259
|
+
border: none;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Loading Skeleton */
|
|
264
|
+
.jupiter-modal-skeleton {
|
|
265
|
+
position: absolute;
|
|
266
|
+
inset: 0;
|
|
267
|
+
background-color: #1a1a1a;
|
|
268
|
+
padding: 1.5rem;
|
|
269
|
+
padding-top: 32px;
|
|
270
|
+
display: flex;
|
|
271
|
+
flex-direction: column;
|
|
272
|
+
gap: 32px;
|
|
273
|
+
z-index: 1;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.jupiter-modal-skeleton.hidden {
|
|
277
|
+
display: none;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@media (min-width: 768px) {
|
|
281
|
+
.jupiter-modal-skeleton {
|
|
282
|
+
height: 600px;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.jupiter-skeleton-item {
|
|
287
|
+
background-color: #2a2a2a;
|
|
288
|
+
border-radius: 0.5rem;
|
|
289
|
+
animation: skeleton-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
@keyframes skeleton-pulse {
|
|
293
|
+
0%, 100% {
|
|
294
|
+
opacity: 1;
|
|
295
|
+
}
|
|
296
|
+
50% {
|
|
297
|
+
opacity: 0.5;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
`;
|
|
301
|
+
const SKELETON_HTML = `
|
|
302
|
+
<div style="display: flex; gap: 12px;">
|
|
303
|
+
<div class="jupiter-skeleton-item" style="width: 48px; height: 48px; border-radius: 50%;"></div>
|
|
304
|
+
<div >
|
|
305
|
+
<p class="jupiter-skeleton-item" style="width: 180px; height: 20px; border-radius: 12px; margin-bottom: 8px"></p>
|
|
306
|
+
<p class="jupiter-skeleton-item" style="width: 100px; height: 16px; border-radius: 12px"></p>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
<div style="display: flex; justify-content: center; align-items: center; flex-direction: column; gap: 12px">
|
|
310
|
+
<p class="jupiter-skeleton-item" style="width: 80px; height: 28px; border-radius: 18px"></p>
|
|
311
|
+
<p class="jupiter-skeleton-item" style="width: 220px; height: 40px; border-radius: 24px"></p>
|
|
312
|
+
</div>
|
|
313
|
+
<div style="height:2px background-color: #e5e7eb;"></div>
|
|
314
|
+
<div class="jupiter-skeleton-item" style="width: 300px; height: 28px; align-self: center; border-radius: 18px"></div>
|
|
315
|
+
<div style="display: flex; flex-direction: column; gap: 12px; justify-content: center; align-items: center;">
|
|
316
|
+
<div class="jupiter-skeleton-item" style="width: 375px; height: 64px; border-radius: calc(infinity * 1px)"></div>
|
|
317
|
+
<div class="jupiter-skeleton-item" style="width: 375px; height: 64px; border-radius: calc(infinity * 1px)"></div>
|
|
318
|
+
<div class="jupiter-skeleton-item" style="width: 375px; height: 64px; border-radius: calc(infinity * 1px)"></div>
|
|
319
|
+
</div>
|
|
320
|
+
`;
|
|
321
|
+
class Modal {
|
|
322
|
+
constructor() {
|
|
323
|
+
this.isOpen = false;
|
|
324
|
+
this.overlay = null;
|
|
325
|
+
this.container = null;
|
|
326
|
+
this.closeButton = null;
|
|
327
|
+
this.iframe = null;
|
|
328
|
+
this.skeleton = null;
|
|
329
|
+
this.initialized = false;
|
|
330
|
+
this.onCloseCallback = null;
|
|
331
|
+
this.messageHandler = null;
|
|
332
|
+
}
|
|
333
|
+
static getInstance() {
|
|
334
|
+
if (!Modal.instance) {
|
|
335
|
+
Modal.instance = new Modal();
|
|
336
|
+
}
|
|
337
|
+
return Modal.instance;
|
|
338
|
+
}
|
|
339
|
+
injectStyles() {
|
|
340
|
+
if (document.getElementById("jupiter-modal-styles")) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const style = document.createElement("style");
|
|
344
|
+
style.id = "jupiter-modal-styles";
|
|
345
|
+
style.textContent = MODAL_STYLES;
|
|
346
|
+
document.head.appendChild(style);
|
|
347
|
+
}
|
|
348
|
+
initializeElements() {
|
|
349
|
+
if (this.initialized) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
this.injectStyles();
|
|
353
|
+
// Create overlay
|
|
354
|
+
this.overlay = document.createElement("div");
|
|
355
|
+
this.overlay.className = "jupiter-modal-overlay";
|
|
356
|
+
this.overlay.addEventListener("click", (e) => {
|
|
357
|
+
if (e.target === this.overlay) {
|
|
358
|
+
this.close();
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
document.body.appendChild(this.overlay);
|
|
362
|
+
// Create container
|
|
363
|
+
this.container = document.createElement("div");
|
|
364
|
+
this.container.className = "jupiter-modal-container";
|
|
365
|
+
// Create close button
|
|
366
|
+
this.closeButton = document.createElement("button");
|
|
367
|
+
this.closeButton.className = "jupiter-modal-close";
|
|
368
|
+
this.closeButton.setAttribute("aria-label", "Close");
|
|
369
|
+
this.closeButton.innerHTML = `
|
|
370
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
371
|
+
<path d="M18 6 6 18"></path>
|
|
372
|
+
<path d="m6 6 12 12"></path>
|
|
373
|
+
</svg>
|
|
374
|
+
`;
|
|
375
|
+
this.closeButton.addEventListener("click", (e) => {
|
|
376
|
+
e.preventDefault();
|
|
377
|
+
e.stopPropagation();
|
|
378
|
+
this.close();
|
|
379
|
+
});
|
|
380
|
+
this.container.appendChild(this.closeButton);
|
|
381
|
+
// Create skeleton
|
|
382
|
+
this.skeleton = document.createElement("div");
|
|
383
|
+
this.skeleton.className = "jupiter-modal-skeleton hidden";
|
|
384
|
+
this.skeleton.innerHTML = SKELETON_HTML;
|
|
385
|
+
this.container.appendChild(this.skeleton);
|
|
386
|
+
// Add container to body
|
|
387
|
+
document.body.appendChild(this.container);
|
|
388
|
+
this.initialized = true;
|
|
389
|
+
}
|
|
390
|
+
showModal(url) {
|
|
391
|
+
// Show skeleton loader
|
|
392
|
+
this.skeleton.classList.remove("hidden");
|
|
393
|
+
// Create iframe (hidden initially)
|
|
394
|
+
this.iframe = document.createElement("iframe");
|
|
395
|
+
this.iframe.className = "jupiter-modal-iframe";
|
|
396
|
+
this.iframe.src = url;
|
|
397
|
+
this.iframe.setAttribute("allow", "payment");
|
|
398
|
+
this.iframe.style.opacity = "0";
|
|
399
|
+
this.container.appendChild(this.iframe);
|
|
400
|
+
// Show iframe and hide skeleton once loaded
|
|
401
|
+
this.iframe.addEventListener("load", () => {
|
|
402
|
+
if (this.iframe && this.skeleton) {
|
|
403
|
+
this.skeleton.classList.add("hidden");
|
|
404
|
+
this.iframe.style.opacity = "1";
|
|
405
|
+
this.iframe.style.transition = "opacity 0.3s ease-out";
|
|
406
|
+
}
|
|
407
|
+
}, { once: true });
|
|
408
|
+
// Show overlay and container
|
|
409
|
+
this.overlay.classList.add("open");
|
|
410
|
+
this.container.classList.add("open");
|
|
411
|
+
// Prevent body scroll when modal is open
|
|
412
|
+
document.body.style.overflow = "hidden";
|
|
413
|
+
}
|
|
414
|
+
hideModal() {
|
|
415
|
+
var _a, _b, _c, _d;
|
|
416
|
+
// Remove open class first, then add closing class
|
|
417
|
+
(_a = this.overlay) === null || _a === void 0 ? void 0 : _a.classList.remove("open");
|
|
418
|
+
(_b = this.container) === null || _b === void 0 ? void 0 : _b.classList.remove("open");
|
|
419
|
+
(_c = this.overlay) === null || _c === void 0 ? void 0 : _c.classList.add("closing");
|
|
420
|
+
(_d = this.container) === null || _d === void 0 ? void 0 : _d.classList.add("closing");
|
|
421
|
+
// Remove classes and iframe after animation completes
|
|
422
|
+
setTimeout(() => {
|
|
423
|
+
var _a, _b;
|
|
424
|
+
(_a = this.overlay) === null || _a === void 0 ? void 0 : _a.classList.remove("closing");
|
|
425
|
+
(_b = this.container) === null || _b === void 0 ? void 0 : _b.classList.remove("closing");
|
|
426
|
+
// Restore body scroll
|
|
427
|
+
document.body.style.overflow = "";
|
|
428
|
+
// Remove iframe
|
|
429
|
+
if (this.iframe) {
|
|
430
|
+
this.iframe.remove();
|
|
431
|
+
this.iframe = null;
|
|
432
|
+
}
|
|
433
|
+
}, 300);
|
|
434
|
+
}
|
|
435
|
+
open(url, onClose, onMessage) {
|
|
436
|
+
// If already open, do nothing
|
|
437
|
+
if (this.isOpen) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
this.isOpen = true;
|
|
441
|
+
this.onCloseCallback = onClose || null;
|
|
442
|
+
// Set up message listener if callback provided
|
|
443
|
+
if (onMessage) {
|
|
444
|
+
this.messageHandler = onMessage;
|
|
445
|
+
window.addEventListener("message", this.messageHandler);
|
|
446
|
+
}
|
|
447
|
+
this.initializeElements();
|
|
448
|
+
this.showModal(url);
|
|
449
|
+
}
|
|
450
|
+
close() {
|
|
451
|
+
if (!this.isOpen) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
this.isOpen = false;
|
|
455
|
+
this.hideModal();
|
|
456
|
+
// Remove message listener if it exists
|
|
457
|
+
if (this.messageHandler) {
|
|
458
|
+
window.removeEventListener("message", this.messageHandler);
|
|
459
|
+
this.messageHandler = null;
|
|
460
|
+
}
|
|
461
|
+
// Call onClose callback if provided
|
|
462
|
+
if (this.onCloseCallback) {
|
|
463
|
+
this.onCloseCallback();
|
|
464
|
+
this.onCloseCallback = null;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
destroy() {
|
|
468
|
+
this.close();
|
|
469
|
+
// Wait for close animation to complete before removing elements
|
|
470
|
+
setTimeout(() => {
|
|
471
|
+
var _a, _b;
|
|
472
|
+
(_a = this.overlay) === null || _a === void 0 ? void 0 : _a.remove();
|
|
473
|
+
(_b = this.container) === null || _b === void 0 ? void 0 : _b.remove();
|
|
474
|
+
this.overlay = null;
|
|
475
|
+
this.container = null;
|
|
476
|
+
this.closeButton = null;
|
|
477
|
+
this.iframe = null;
|
|
478
|
+
this.skeleton = null;
|
|
479
|
+
this.initialized = false;
|
|
480
|
+
Modal.instance = null;
|
|
481
|
+
}, 350);
|
|
482
|
+
}
|
|
483
|
+
static destroyInstance() {
|
|
484
|
+
if (Modal.instance) {
|
|
485
|
+
Modal.instance.destroy();
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
Modal.instance = null;
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Main Jupiter SDK class
|
|
493
|
+
*/
|
|
494
|
+
class Jupiter {
|
|
495
|
+
/**
|
|
496
|
+
* Initialize the Jupiter SDK
|
|
497
|
+
*
|
|
498
|
+
* @param config - Configuration options
|
|
499
|
+
*
|
|
500
|
+
* @example
|
|
501
|
+
* ```js
|
|
502
|
+
* const jupiter = new Jupiter({
|
|
503
|
+
* apiKey: 'jup_prod-xxxxx',
|
|
504
|
+
* environment: 'production'
|
|
505
|
+
* });
|
|
506
|
+
* ```
|
|
507
|
+
*/
|
|
508
|
+
constructor(config) {
|
|
509
|
+
this.isInUse = false;
|
|
510
|
+
// Validate API key
|
|
511
|
+
if (!config.apiKey) {
|
|
512
|
+
throw {
|
|
513
|
+
code: "INVALID_CONFIG",
|
|
514
|
+
message: "apiKey is required",
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
// Set configuration
|
|
518
|
+
this.environment = config.environment || "production";
|
|
519
|
+
this.api = new JupiterAPI(config);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Authorize a payment amount and open loan application flow
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```js
|
|
526
|
+
* jupiter.authorize({
|
|
527
|
+
* amount: 100000, // $1,000.00 in cents
|
|
528
|
+
* referenceId: "order_12345",
|
|
529
|
+
* onComplete: ({ loanId, status, referenceId }) => {
|
|
530
|
+
* console.log('Loan', loanId, 'is', status);
|
|
531
|
+
* },
|
|
532
|
+
* onCancel: () => console.log('User cancelled'),
|
|
533
|
+
* onError: (error) => console.error(error)
|
|
534
|
+
* });
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
537
|
+
authorize({ amount, referenceId, onComplete, onCancel, onError, modalTimeout, }) {
|
|
538
|
+
// Prevent multiple concurrent authorizations
|
|
539
|
+
if (this.isInUse) {
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
// Validate inputs (throw immediately, don't call onError)
|
|
543
|
+
if (typeof amount !== "number" || amount <= 0) {
|
|
544
|
+
throw {
|
|
545
|
+
code: "INVALID_AMOUNT",
|
|
546
|
+
message: "Amount must be a positive number in cents",
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
if (referenceId && referenceId.length > 255) {
|
|
550
|
+
throw {
|
|
551
|
+
code: "INVALID_REFERENCE_ID",
|
|
552
|
+
message: "Reference ID must be 255 characters or less",
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
this.isInUse = true;
|
|
556
|
+
// Handle API call asynchronously internally
|
|
557
|
+
this.api
|
|
558
|
+
.createPaymentLink(amount, referenceId)
|
|
559
|
+
.then((paymentLink) => {
|
|
560
|
+
const paymentUrl = `${APP_URLS[this.environment]}/pay/${paymentLink.slug}`;
|
|
561
|
+
// Track if authorization was completed via message
|
|
562
|
+
let wasCompleted = false;
|
|
563
|
+
const modal = Modal.getInstance();
|
|
564
|
+
modal.open(paymentUrl,
|
|
565
|
+
// onClose
|
|
566
|
+
() => {
|
|
567
|
+
this.isInUse = false;
|
|
568
|
+
// If modal closes without completion message, treat as cancel
|
|
569
|
+
if (!wasCompleted) {
|
|
570
|
+
onCancel();
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
// onMessage
|
|
574
|
+
(event) => {
|
|
575
|
+
if (event.origin !== new URL(APP_URLS[this.environment]).origin) {
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
if (event.data.type === "jupiter_loan_status") {
|
|
579
|
+
wasCompleted = true;
|
|
580
|
+
setTimeout(() => {
|
|
581
|
+
modal.close();
|
|
582
|
+
}, modalTimeout !== null && modalTimeout !== void 0 ? modalTimeout : 5000);
|
|
583
|
+
this.isInUse = false;
|
|
584
|
+
onComplete({
|
|
585
|
+
loanId: event.data.loanId,
|
|
586
|
+
status: event.data.status,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
})
|
|
591
|
+
.catch((error) => {
|
|
592
|
+
this.isInUse = false;
|
|
593
|
+
onError(error);
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Jupiter JavaScript SDK
|
|
600
|
+
*
|
|
601
|
+
* @packageDocumentation
|
|
602
|
+
*/
|
|
603
|
+
// For UMD build - expose on window object
|
|
604
|
+
if (typeof window !== "undefined") {
|
|
605
|
+
window.Jupiter = Jupiter;
|
|
606
|
+
window.JupiterModal = Modal;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
exports.Jupiter = Jupiter;
|
|
610
|
+
exports.Modal = Modal;
|
|
611
|
+
|
|
612
|
+
}));
|
|
613
|
+
//# sourceMappingURL=index.umd.js.map
|