@coincircuit/checkout 0.2.2 → 0.3.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.
@@ -43,10 +43,11 @@ function createMessageListener(allowedOrigin, handlers) {
43
43
  }
44
44
 
45
45
  // src/utils.ts
46
- var DEFAULT_BASE_URL = "https://checkout.coincircuit.io";
46
+ var DEFAULT_BASE_URL = "http://localhost:3002";
47
47
  var ALLOWED_BASE_URLS = [
48
48
  "https://checkout.coincircuit.io",
49
- "https://sandbox-checkout.coincircuit.io"
49
+ "https://sandbox-checkout.coincircuit.io",
50
+ "http://localhost:3002"
50
51
  ];
51
52
  function validateBaseUrl(url) {
52
53
  const normalized = url.replace(/\/+$/, "");
@@ -102,6 +103,13 @@ function injectStyles() {
102
103
  border-radius: 16px;
103
104
  background: #fff;
104
105
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4);
106
+ opacity: 0;
107
+ transform: scale(0.96);
108
+ transition: opacity 0.25s ease, transform 0.25s ease;
109
+ }
110
+ #${OVERLAY_ID} .cc-modal.cc-ready {
111
+ opacity: 1;
112
+ transform: scale(1);
105
113
  }
106
114
  #${OVERLAY_ID} .cc-close {
107
115
  position: fixed;
@@ -139,14 +147,14 @@ function injectStyles() {
139
147
  display: flex;
140
148
  align-items: center;
141
149
  justify-content: center;
142
- background: #fff;
150
+ z-index: 1;
143
151
  transition: opacity 0.2s;
144
152
  }
145
153
  #${OVERLAY_ID} .cc-spinner div {
146
154
  width: 36px;
147
155
  height: 36px;
148
- border: 3px solid #e5e7eb;
149
- border-top-color: #6366f1;
156
+ border: 3px solid rgba(255, 255, 255, 0.3);
157
+ border-top-color: #fff;
150
158
  border-radius: 50%;
151
159
  animation: cc-spin 0.8s linear infinite;
152
160
  }
@@ -179,7 +187,8 @@ function createOverlay(checkoutUrl, onCloseClick) {
179
187
  modal.className = "cc-modal";
180
188
  const spinner = document.createElement("div");
181
189
  spinner.className = "cc-spinner";
182
- spinner.innerHTML = "<div></div>";
190
+ const spinnerRing = document.createElement("div");
191
+ spinner.appendChild(spinnerRing);
183
192
  const iframe = document.createElement("iframe");
184
193
  iframe.src = checkoutUrl;
185
194
  iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox");
@@ -191,8 +200,8 @@ function createOverlay(checkoutUrl, onCloseClick) {
191
200
  closeBtn.setAttribute("aria-label", "Close checkout");
192
201
  closeBtn.textContent = "\u2715";
193
202
  closeBtn.addEventListener("click", onCloseClick);
194
- modal.appendChild(spinner);
195
203
  modal.appendChild(iframe);
204
+ overlay.appendChild(spinner);
196
205
  overlay.appendChild(modal);
197
206
  overlay.appendChild(closeBtn);
198
207
  return { overlay, iframe };
@@ -217,6 +226,10 @@ function hideSpinner(overlay) {
217
226
  spinner.style.opacity = "0";
218
227
  setTimeout(() => spinner.parentNode?.removeChild(spinner), 200);
219
228
  }
229
+ const modal = overlay.querySelector(".cc-modal");
230
+ if (modal) {
231
+ modal.classList.add("cc-ready");
232
+ }
220
233
  }
221
234
  function showErrorToast(message) {
222
235
  const toast = document.createElement("div");
@@ -258,6 +271,7 @@ var CoinCircuitCheckout = class {
258
271
  overlay = null;
259
272
  removeMessageListener = null;
260
273
  loadTimeout = null;
274
+ openedAt = 0;
261
275
  constructor(config = {}) {
262
276
  this.baseUrl = config.baseUrl ? validateBaseUrl(config.baseUrl) : DEFAULT_BASE_URL;
263
277
  this.origin = extractOrigin(this.baseUrl);
@@ -274,6 +288,8 @@ var CoinCircuitCheckout = class {
274
288
  if (!options.reference) {
275
289
  throw new Error('CoinCircuitCheckout: "reference" is required.');
276
290
  }
291
+ this.openedAt = performance.now();
292
+ console.log("[CoinCircuit] open() called \u2014 waiting for coincircuit:ready");
277
293
  const checkoutUrl = buildCheckoutUrl(
278
294
  this.baseUrl,
279
295
  options.reference,
@@ -292,11 +308,17 @@ var CoinCircuitCheckout = class {
292
308
  }, 15e3);
293
309
  iframe.addEventListener("error", () => {
294
310
  if (this.loadTimeout) clearTimeout(this.loadTimeout);
311
+ console.error(`[CoinCircuit] iframe error after ${Math.round(performance.now() - this.openedAt)}ms`);
295
312
  showErrorToast("Checkout failed to load. Please try again.");
296
313
  this.close();
297
314
  });
315
+ iframe.addEventListener("load", () => {
316
+ console.log(`[CoinCircuit] iframe DOM loaded at ${Math.round(performance.now() - this.openedAt)}ms (still waiting for coincircuit:ready)`);
317
+ });
298
318
  this.removeMessageListener = createMessageListener(this.origin, {
299
319
  onReady: () => {
320
+ const elapsed = Math.round(performance.now() - this.openedAt);
321
+ console.log(`[CoinCircuit] coincircuit:ready received at ${elapsed}ms`);
300
322
  if (this.loadTimeout) {
301
323
  clearTimeout(this.loadTimeout);
302
324
  this.loadTimeout = null;
@@ -305,6 +327,7 @@ var CoinCircuitCheckout = class {
305
327
  options.onReady?.();
306
328
  },
307
329
  onPaymentComplete: (data) => {
330
+ console.log(`[CoinCircuit] coincircuit:payment_complete at ${Math.round(performance.now() - this.openedAt)}ms`);
308
331
  options.onPaymentComplete?.(data);
309
332
  },
310
333
  onPaymentFailed: (data) => {
package/dist/index.cjs CHANGED
@@ -74,10 +74,11 @@ function createMessageListener(allowedOrigin, handlers) {
74
74
  }
75
75
 
76
76
  // src/utils.ts
77
- var DEFAULT_BASE_URL = "https://checkout.coincircuit.io";
77
+ var DEFAULT_BASE_URL = "http://localhost:3002";
78
78
  var ALLOWED_BASE_URLS = [
79
79
  "https://checkout.coincircuit.io",
80
- "https://sandbox-checkout.coincircuit.io"
80
+ "https://sandbox-checkout.coincircuit.io",
81
+ "http://localhost:3002"
81
82
  ];
82
83
  function validateBaseUrl(url) {
83
84
  const normalized = url.replace(/\/+$/, "");
@@ -133,6 +134,13 @@ function injectStyles() {
133
134
  border-radius: 16px;
134
135
  background: #fff;
135
136
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4);
137
+ opacity: 0;
138
+ transform: scale(0.96);
139
+ transition: opacity 0.25s ease, transform 0.25s ease;
140
+ }
141
+ #${OVERLAY_ID} .cc-modal.cc-ready {
142
+ opacity: 1;
143
+ transform: scale(1);
136
144
  }
137
145
  #${OVERLAY_ID} .cc-close {
138
146
  position: fixed;
@@ -170,14 +178,14 @@ function injectStyles() {
170
178
  display: flex;
171
179
  align-items: center;
172
180
  justify-content: center;
173
- background: #fff;
181
+ z-index: 1;
174
182
  transition: opacity 0.2s;
175
183
  }
176
184
  #${OVERLAY_ID} .cc-spinner div {
177
185
  width: 36px;
178
186
  height: 36px;
179
- border: 3px solid #e5e7eb;
180
- border-top-color: #6366f1;
187
+ border: 3px solid rgba(255, 255, 255, 0.3);
188
+ border-top-color: #fff;
181
189
  border-radius: 50%;
182
190
  animation: cc-spin 0.8s linear infinite;
183
191
  }
@@ -210,7 +218,8 @@ function createOverlay(checkoutUrl, onCloseClick) {
210
218
  modal.className = "cc-modal";
211
219
  const spinner = document.createElement("div");
212
220
  spinner.className = "cc-spinner";
213
- spinner.innerHTML = "<div></div>";
221
+ const spinnerRing = document.createElement("div");
222
+ spinner.appendChild(spinnerRing);
214
223
  const iframe = document.createElement("iframe");
215
224
  iframe.src = checkoutUrl;
216
225
  iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox");
@@ -222,8 +231,8 @@ function createOverlay(checkoutUrl, onCloseClick) {
222
231
  closeBtn.setAttribute("aria-label", "Close checkout");
223
232
  closeBtn.textContent = "\u2715";
224
233
  closeBtn.addEventListener("click", onCloseClick);
225
- modal.appendChild(spinner);
226
234
  modal.appendChild(iframe);
235
+ overlay.appendChild(spinner);
227
236
  overlay.appendChild(modal);
228
237
  overlay.appendChild(closeBtn);
229
238
  return { overlay, iframe };
@@ -248,6 +257,10 @@ function hideSpinner(overlay) {
248
257
  spinner.style.opacity = "0";
249
258
  setTimeout(() => spinner.parentNode?.removeChild(spinner), 200);
250
259
  }
260
+ const modal = overlay.querySelector(".cc-modal");
261
+ if (modal) {
262
+ modal.classList.add("cc-ready");
263
+ }
251
264
  }
252
265
  function showErrorToast(message) {
253
266
  const toast = document.createElement("div");
@@ -289,6 +302,7 @@ var CoinCircuitCheckout = class {
289
302
  overlay = null;
290
303
  removeMessageListener = null;
291
304
  loadTimeout = null;
305
+ openedAt = 0;
292
306
  constructor(config = {}) {
293
307
  this.baseUrl = config.baseUrl ? validateBaseUrl(config.baseUrl) : DEFAULT_BASE_URL;
294
308
  this.origin = extractOrigin(this.baseUrl);
@@ -305,6 +319,8 @@ var CoinCircuitCheckout = class {
305
319
  if (!options.reference) {
306
320
  throw new Error('CoinCircuitCheckout: "reference" is required.');
307
321
  }
322
+ this.openedAt = performance.now();
323
+ console.log("[CoinCircuit] open() called \u2014 waiting for coincircuit:ready");
308
324
  const checkoutUrl = buildCheckoutUrl(
309
325
  this.baseUrl,
310
326
  options.reference,
@@ -323,11 +339,17 @@ var CoinCircuitCheckout = class {
323
339
  }, 15e3);
324
340
  iframe.addEventListener("error", () => {
325
341
  if (this.loadTimeout) clearTimeout(this.loadTimeout);
342
+ console.error(`[CoinCircuit] iframe error after ${Math.round(performance.now() - this.openedAt)}ms`);
326
343
  showErrorToast("Checkout failed to load. Please try again.");
327
344
  this.close();
328
345
  });
346
+ iframe.addEventListener("load", () => {
347
+ console.log(`[CoinCircuit] iframe DOM loaded at ${Math.round(performance.now() - this.openedAt)}ms (still waiting for coincircuit:ready)`);
348
+ });
329
349
  this.removeMessageListener = createMessageListener(this.origin, {
330
350
  onReady: () => {
351
+ const elapsed = Math.round(performance.now() - this.openedAt);
352
+ console.log(`[CoinCircuit] coincircuit:ready received at ${elapsed}ms`);
331
353
  if (this.loadTimeout) {
332
354
  clearTimeout(this.loadTimeout);
333
355
  this.loadTimeout = null;
@@ -336,6 +358,7 @@ var CoinCircuitCheckout = class {
336
358
  options.onReady?.();
337
359
  },
338
360
  onPaymentComplete: (data) => {
361
+ console.log(`[CoinCircuit] coincircuit:payment_complete at ${Math.round(performance.now() - this.openedAt)}ms`);
339
362
  options.onPaymentComplete?.(data);
340
363
  },
341
364
  onPaymentFailed: (data) => {
package/dist/index.d.cts CHANGED
@@ -24,6 +24,7 @@ declare class CoinCircuitCheckout {
24
24
  private overlay;
25
25
  private removeMessageListener;
26
26
  private loadTimeout;
27
+ private openedAt;
27
28
  constructor(config?: CheckoutConfig);
28
29
  /**
29
30
  * Opens the checkout modal overlay.
@@ -78,7 +79,7 @@ interface CheckoutEventHandlers {
78
79
  */
79
80
  declare function createMessageListener(allowedOrigin: string, handlers: CheckoutEventHandlers): () => void;
80
81
 
81
- declare const DEFAULT_BASE_URL = "https://checkout.coincircuit.io";
82
+ declare const DEFAULT_BASE_URL = "http://localhost:3002";
82
83
  /**
83
84
  * Builds the checkout URL with embed flag.
84
85
  */
package/dist/index.d.ts CHANGED
@@ -24,6 +24,7 @@ declare class CoinCircuitCheckout {
24
24
  private overlay;
25
25
  private removeMessageListener;
26
26
  private loadTimeout;
27
+ private openedAt;
27
28
  constructor(config?: CheckoutConfig);
28
29
  /**
29
30
  * Opens the checkout modal overlay.
@@ -78,7 +79,7 @@ interface CheckoutEventHandlers {
78
79
  */
79
80
  declare function createMessageListener(allowedOrigin: string, handlers: CheckoutEventHandlers): () => void;
80
81
 
81
- declare const DEFAULT_BASE_URL = "https://checkout.coincircuit.io";
82
+ declare const DEFAULT_BASE_URL = "http://localhost:3002";
82
83
  /**
83
84
  * Builds the checkout URL with embed flag.
84
85
  */
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  buildCheckoutUrl,
6
6
  createMessageListener,
7
7
  extractOrigin
8
- } from "./chunk-DG6Y255K.js";
8
+ } from "./chunk-IC5IZ3JH.js";
9
9
  export {
10
10
  CHECKOUT_MESSAGE_TYPES,
11
11
  CoinCircuitCheckout,
package/dist/react.cjs CHANGED
@@ -70,10 +70,11 @@ function createMessageListener(allowedOrigin, handlers) {
70
70
  }
71
71
 
72
72
  // src/utils.ts
73
- var DEFAULT_BASE_URL = "https://checkout.coincircuit.io";
73
+ var DEFAULT_BASE_URL = "http://localhost:3002";
74
74
  var ALLOWED_BASE_URLS = [
75
75
  "https://checkout.coincircuit.io",
76
- "https://sandbox-checkout.coincircuit.io"
76
+ "https://sandbox-checkout.coincircuit.io",
77
+ "http://localhost:3002"
77
78
  ];
78
79
  function validateBaseUrl(url) {
79
80
  const normalized = url.replace(/\/+$/, "");
@@ -129,6 +130,13 @@ function injectStyles() {
129
130
  border-radius: 16px;
130
131
  background: #fff;
131
132
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4);
133
+ opacity: 0;
134
+ transform: scale(0.96);
135
+ transition: opacity 0.25s ease, transform 0.25s ease;
136
+ }
137
+ #${OVERLAY_ID} .cc-modal.cc-ready {
138
+ opacity: 1;
139
+ transform: scale(1);
132
140
  }
133
141
  #${OVERLAY_ID} .cc-close {
134
142
  position: fixed;
@@ -166,14 +174,14 @@ function injectStyles() {
166
174
  display: flex;
167
175
  align-items: center;
168
176
  justify-content: center;
169
- background: #fff;
177
+ z-index: 1;
170
178
  transition: opacity 0.2s;
171
179
  }
172
180
  #${OVERLAY_ID} .cc-spinner div {
173
181
  width: 36px;
174
182
  height: 36px;
175
- border: 3px solid #e5e7eb;
176
- border-top-color: #6366f1;
183
+ border: 3px solid rgba(255, 255, 255, 0.3);
184
+ border-top-color: #fff;
177
185
  border-radius: 50%;
178
186
  animation: cc-spin 0.8s linear infinite;
179
187
  }
@@ -206,7 +214,8 @@ function createOverlay(checkoutUrl, onCloseClick) {
206
214
  modal.className = "cc-modal";
207
215
  const spinner = document.createElement("div");
208
216
  spinner.className = "cc-spinner";
209
- spinner.innerHTML = "<div></div>";
217
+ const spinnerRing = document.createElement("div");
218
+ spinner.appendChild(spinnerRing);
210
219
  const iframe = document.createElement("iframe");
211
220
  iframe.src = checkoutUrl;
212
221
  iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox");
@@ -218,8 +227,8 @@ function createOverlay(checkoutUrl, onCloseClick) {
218
227
  closeBtn.setAttribute("aria-label", "Close checkout");
219
228
  closeBtn.textContent = "\u2715";
220
229
  closeBtn.addEventListener("click", onCloseClick);
221
- modal.appendChild(spinner);
222
230
  modal.appendChild(iframe);
231
+ overlay.appendChild(spinner);
223
232
  overlay.appendChild(modal);
224
233
  overlay.appendChild(closeBtn);
225
234
  return { overlay, iframe };
@@ -244,6 +253,10 @@ function hideSpinner(overlay) {
244
253
  spinner.style.opacity = "0";
245
254
  setTimeout(() => spinner.parentNode?.removeChild(spinner), 200);
246
255
  }
256
+ const modal = overlay.querySelector(".cc-modal");
257
+ if (modal) {
258
+ modal.classList.add("cc-ready");
259
+ }
247
260
  }
248
261
  function showErrorToast(message) {
249
262
  const toast = document.createElement("div");
@@ -285,6 +298,7 @@ var CoinCircuitCheckout = class {
285
298
  overlay = null;
286
299
  removeMessageListener = null;
287
300
  loadTimeout = null;
301
+ openedAt = 0;
288
302
  constructor(config = {}) {
289
303
  this.baseUrl = config.baseUrl ? validateBaseUrl(config.baseUrl) : DEFAULT_BASE_URL;
290
304
  this.origin = extractOrigin(this.baseUrl);
@@ -301,6 +315,8 @@ var CoinCircuitCheckout = class {
301
315
  if (!options.reference) {
302
316
  throw new Error('CoinCircuitCheckout: "reference" is required.');
303
317
  }
318
+ this.openedAt = performance.now();
319
+ console.log("[CoinCircuit] open() called \u2014 waiting for coincircuit:ready");
304
320
  const checkoutUrl = buildCheckoutUrl(
305
321
  this.baseUrl,
306
322
  options.reference,
@@ -319,11 +335,17 @@ var CoinCircuitCheckout = class {
319
335
  }, 15e3);
320
336
  iframe.addEventListener("error", () => {
321
337
  if (this.loadTimeout) clearTimeout(this.loadTimeout);
338
+ console.error(`[CoinCircuit] iframe error after ${Math.round(performance.now() - this.openedAt)}ms`);
322
339
  showErrorToast("Checkout failed to load. Please try again.");
323
340
  this.close();
324
341
  });
342
+ iframe.addEventListener("load", () => {
343
+ console.log(`[CoinCircuit] iframe DOM loaded at ${Math.round(performance.now() - this.openedAt)}ms (still waiting for coincircuit:ready)`);
344
+ });
325
345
  this.removeMessageListener = createMessageListener(this.origin, {
326
346
  onReady: () => {
347
+ const elapsed = Math.round(performance.now() - this.openedAt);
348
+ console.log(`[CoinCircuit] coincircuit:ready received at ${elapsed}ms`);
327
349
  if (this.loadTimeout) {
328
350
  clearTimeout(this.loadTimeout);
329
351
  this.loadTimeout = null;
@@ -332,6 +354,7 @@ var CoinCircuitCheckout = class {
332
354
  options.onReady?.();
333
355
  },
334
356
  onPaymentComplete: (data) => {
357
+ console.log(`[CoinCircuit] coincircuit:payment_complete at ${Math.round(performance.now() - this.openedAt)}ms`);
335
358
  options.onPaymentComplete?.(data);
336
359
  },
337
360
  onPaymentFailed: (data) => {
package/dist/react.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  CoinCircuitCheckout
3
- } from "./chunk-DG6Y255K.js";
3
+ } from "./chunk-IC5IZ3JH.js";
4
4
 
5
5
  // src/react.ts
6
6
  import { useRef, useCallback, useEffect, createElement } from "react";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coincircuit/checkout",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Embed CoinCircuit checkout in your site via iframe, with vanilla JS and React support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",