@funnelsgrove/payments 0.7.11 → 0.7.13

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.
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { publicAnalyticsSdk } from '@funnelsgrove/analytics';
4
4
  import { Suspense, lazy, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
5
5
  import { pollSolidgateCheckoutStatus, prepareSolidgateCheckout, } from '../services/solidgate.service.js';
@@ -84,7 +84,7 @@ function SolidgatePaymentForm({ checkout, hidden, loadingLabel, onError, onMount
84
84
  safeDestroyPaymentForm(instanceRef.current);
85
85
  instanceRef.current = null;
86
86
  }, [checkout.attemptId]);
87
- return (_jsxs("div", { className: hidden ? 'hidden' : 'block', "data-solidgate-attempt-id": checkout.attemptId, "aria-hidden": hidden || undefined, children: [_jsxs("div", { className: 'mb-3 grid gap-3', children: [_jsx("div", { ref: applePayContainerRef, "data-solidgate-wallet": 'apple-pay' }), _jsx("div", { ref: googlePayContainerRef, "data-solidgate-wallet": 'google-pay' })] }), _jsx(Suspense, { fallback: (_jsx("p", { role: 'status', className: 'text-sm text-muted-foreground', children: loadingLabel })), children: _jsx(SolidgatePayment, { merchantData: checkout.initialization.merchantData, width: '100%', formParams: { isSolidLogoVisible: true }, applePayContainerRef: applePayContainerRef, googlePayContainerRef: googlePayContainerRef, onReadyPaymentInstance: (instance) => {
87
+ return (_jsxs("div", { className: 'solidgate-checkout-payment', "data-solidgate-attempt-id": checkout.attemptId, hidden: hidden, "aria-hidden": hidden || undefined, children: [_jsxs("div", { className: 'solidgate-checkout-wallets', children: [_jsx("div", { ref: applePayContainerRef, "data-solidgate-wallet": 'apple-pay' }), _jsx("div", { ref: googlePayContainerRef, "data-solidgate-wallet": 'google-pay' })] }), _jsx(Suspense, { fallback: (_jsx("p", { role: 'status', className: 'solidgate-checkout-status-text', children: loadingLabel })), children: _jsx(SolidgatePayment, { merchantData: checkout.initialization.merchantData, width: '100%', formParams: { isSolidLogoVisible: true }, applePayContainerRef: applePayContainerRef, googlePayContainerRef: googlePayContainerRef, onReadyPaymentInstance: (instance) => {
88
88
  if (instanceRef.current && instanceRef.current !== instance) {
89
89
  try {
90
90
  instanceRef.current.unsubscribeAll();
@@ -111,16 +111,18 @@ export function SolidgateCheckoutDialog({ open, request, customerEmail, checkout
111
111
  const checkoutAnalyticsRef = useRef(checkoutAnalytics);
112
112
  const closeButtonRef = useRef(null);
113
113
  const copyRef = useRef(copy);
114
+ const onCloseRef = useRef(onClose);
114
115
  const onErrorRef = useRef(onError);
115
116
  const onStateChangeRef = useRef(onStateChange);
116
117
  const onSuccessRef = useRef(onSuccess);
117
118
  useEffect(() => {
118
119
  checkoutAnalyticsRef.current = checkoutAnalytics;
119
120
  copyRef.current = copy;
121
+ onCloseRef.current = onClose;
120
122
  onErrorRef.current = onError;
121
123
  onStateChangeRef.current = onStateChange;
122
124
  onSuccessRef.current = onSuccess;
123
- }, [checkoutAnalytics, copy, onError, onStateChange, onSuccess]);
125
+ }, [checkoutAnalytics, copy, onClose, onError, onStateChange, onSuccess]);
124
126
  useEffect(() => {
125
127
  setEmailInput((customerEmail === null || customerEmail === void 0 ? void 0 : customerEmail.trim()) || '');
126
128
  setCommittedEmail(normalizedCustomerEmail);
@@ -221,7 +223,7 @@ export function SolidgateCheckoutDialog({ open, request, customerEmail, checkout
221
223
  : null;
222
224
  const handleKeyDown = (event) => {
223
225
  if (event.key === 'Escape') {
224
- onClose();
226
+ onCloseRef.current();
225
227
  }
226
228
  };
227
229
  window.addEventListener('keydown', handleKeyDown);
@@ -230,7 +232,7 @@ export function SolidgateCheckoutDialog({ open, request, customerEmail, checkout
230
232
  window.removeEventListener('keydown', handleKeyDown);
231
233
  previouslyFocused === null || previouslyFocused === void 0 ? void 0 : previouslyFocused.focus();
232
234
  };
233
- }, [onClose, open]);
235
+ }, [open]);
234
236
  useEffect(() => () => {
235
237
  var _a, _b;
236
238
  (_a = prepareAbortRef.current) === null || _a === void 0 ? void 0 : _a.abort();
@@ -328,23 +330,178 @@ export function SolidgateCheckoutDialog({ open, request, customerEmail, checkout
328
330
  : view.state === 'recoverable_error'
329
331
  ? copy.error
330
332
  : null;
331
- return (_jsx("div", { className: 'fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4', children: _jsxs("div", { role: 'dialog', "aria-modal": 'true', "aria-labelledby": 'solidgate-checkout-title', "data-checkout-state": view.state, className: 'w-full max-w-lg rounded-2xl border border-border bg-card p-5 text-foreground shadow-xl', children: [_jsxs("div", { className: 'mb-4 flex items-center justify-between gap-4', children: [_jsx("h2", { id: 'solidgate-checkout-title', className: 'text-lg font-semibold text-foreground', children: copy.title }), _jsx("button", { ref: closeButtonRef, type: 'button', onClick: onClose, "aria-label": copy.closeAriaLabel, className: 'rounded-md border border-border bg-background px-3 py-1.5 text-foreground hover:bg-accent', children: "\u00D7" })] }), view.state === 'collecting_email' ? (_jsxs("form", { className: 'grid gap-4', onSubmit: (event) => void commitCustomerEmail(event), children: [_jsxs("label", { className: 'grid gap-2 text-sm font-medium text-foreground', children: [copy.customerEmailLabel, _jsx("input", { type: 'email', autoComplete: 'email', inputMode: 'email', maxLength: 320, required: true, value: emailInput, onChange: (event) => {
332
- setEmailInput(event.target.value);
333
- setEmailError(null);
334
- }, placeholder: copy.customerEmailPlaceholder, "aria-invalid": Boolean(emailError), className: 'w-full rounded-lg border border-border bg-background px-3 py-2 text-foreground placeholder:text-muted-foreground' })] }), emailError ? (_jsx("p", { role: 'alert', className: 'text-sm text-destructive', children: emailError })) : null, _jsx("button", { type: 'submit', disabled: emailSubmitting, className: 'w-full rounded-lg border border-border bg-accent px-4 py-2 font-medium text-foreground disabled:opacity-60', children: copy.customerEmailContinue })] })) : null, view.checkout ? (_jsx(SolidgatePaymentForm, { checkout: view.checkout, hidden: !showForm, loadingLabel: copy.loading, onMounted: () => {
335
- if (view.state === 'loading') {
336
- setState(Object.assign(Object.assign({}, view), { state: 'ready' }));
337
- }
338
- }, onSubmit: () => {
339
- var _a, _b, _c;
340
- if (paymentInfoAttemptRef.current !== ((_a = view.checkout) === null || _a === void 0 ? void 0 : _a.attemptId)) {
341
- paymentInfoAttemptRef.current = ((_b = view.checkout) === null || _b === void 0 ? void 0 : _b.attemptId) || null;
342
- void trackSolidgateCheckoutEvent('add_payment_info', ((_c = view.checkout) === null || _c === void 0 ? void 0 : _c.attemptId) || '', checkoutAnalyticsRef.current);
343
- }
344
- setState(Object.assign(Object.assign({}, view), { state: 'submitting' }));
345
- }, onVerify: () => void verifyCanonicalStatus(), onError: () => {
346
- var _a;
347
- setState(Object.assign(Object.assign({}, view), { state: 'recoverable_error', canResumeVerification: false }));
348
- (_a = onErrorRef.current) === null || _a === void 0 ? void 0 : _a.call(onErrorRef, copyRef.current.error);
349
- } }, view.checkout.attemptId)) : null, statusMessage && view.state !== 'ready' ? (_jsx("div", { className: 'rounded-xl border border-border bg-background p-4 text-sm text-muted-foreground', children: _jsx("p", { role: 'status', "aria-live": 'polite', children: statusMessage }) })) : null, view.state === 'verifying' && view.canResumeVerification ? (_jsx("button", { type: 'button', onClick: () => void verifyCanonicalStatus(), className: 'mt-4 w-full rounded-lg border border-border bg-accent px-4 py-2 font-medium text-foreground', children: copy.resumeVerification })) : null, (view.state === 'recoverable_error' || view.state === 'expired') && onRetry ? (_jsx("button", { type: 'button', onClick: onRetry, className: 'mt-4 w-full rounded-lg border border-border bg-accent px-4 py-2 font-medium text-foreground', children: copy.retry })) : null] }) }));
333
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: 'solidgate-checkout-overlay', children: _jsxs("div", { role: 'dialog', "aria-modal": 'true', "aria-labelledby": 'solidgate-checkout-title', "data-checkout-state": view.state, className: 'solidgate-checkout-dialog', children: [_jsxs("div", { className: 'solidgate-checkout-header', children: [_jsx("h2", { id: 'solidgate-checkout-title', className: 'solidgate-checkout-title', children: copy.title }), _jsx("button", { ref: closeButtonRef, type: 'button', onClick: onClose, "aria-label": copy.closeAriaLabel, className: 'solidgate-checkout-close', children: "\u00D7" })] }), view.state === 'collecting_email' ? (_jsxs("form", { className: 'solidgate-checkout-email-form', onSubmit: (event) => void commitCustomerEmail(event), children: [_jsxs("label", { className: 'solidgate-checkout-email-label', children: [copy.customerEmailLabel, _jsx("input", { type: 'email', autoComplete: 'email', inputMode: 'email', maxLength: 320, required: true, value: emailInput, onChange: (event) => {
334
+ setEmailInput(event.target.value);
335
+ setEmailError(null);
336
+ }, placeholder: copy.customerEmailPlaceholder, "aria-invalid": Boolean(emailError), className: 'solidgate-checkout-email-input' })] }), emailError ? (_jsx("p", { role: 'alert', className: 'solidgate-checkout-alert', children: emailError })) : null, _jsx("button", { type: 'submit', disabled: emailSubmitting, className: 'solidgate-checkout-action', children: copy.customerEmailContinue })] })) : null, view.checkout ? (_jsx(SolidgatePaymentForm, { checkout: view.checkout, hidden: !showForm, loadingLabel: copy.loading, onMounted: () => {
337
+ if (view.state === 'loading') {
338
+ setState(Object.assign(Object.assign({}, view), { state: 'ready' }));
339
+ }
340
+ }, onSubmit: () => {
341
+ var _a, _b, _c;
342
+ if (paymentInfoAttemptRef.current !== ((_a = view.checkout) === null || _a === void 0 ? void 0 : _a.attemptId)) {
343
+ paymentInfoAttemptRef.current = ((_b = view.checkout) === null || _b === void 0 ? void 0 : _b.attemptId) || null;
344
+ void trackSolidgateCheckoutEvent('add_payment_info', ((_c = view.checkout) === null || _c === void 0 ? void 0 : _c.attemptId) || '', checkoutAnalyticsRef.current);
345
+ }
346
+ setState(Object.assign(Object.assign({}, view), { state: 'submitting' }));
347
+ }, onVerify: () => void verifyCanonicalStatus(), onError: () => {
348
+ var _a;
349
+ setState(Object.assign(Object.assign({}, view), { state: 'recoverable_error', canResumeVerification: false }));
350
+ (_a = onErrorRef.current) === null || _a === void 0 ? void 0 : _a.call(onErrorRef, copyRef.current.error);
351
+ } }, view.checkout.attemptId)) : null, statusMessage && view.state !== 'ready' ? (_jsx("div", { className: 'solidgate-checkout-status', children: _jsx("p", { role: 'status', "aria-live": 'polite', children: statusMessage }) })) : null, view.state === 'verifying' && view.canResumeVerification ? (_jsx("button", { type: 'button', onClick: () => void verifyCanonicalStatus(), className: 'solidgate-checkout-action solidgate-checkout-action--spaced', children: copy.resumeVerification })) : null, (view.state === 'recoverable_error' || view.state === 'expired') && onRetry ? (_jsx("button", { type: 'button', onClick: onRetry, className: 'solidgate-checkout-action solidgate-checkout-action--spaced', children: copy.retry })) : null] }) }), _jsx("style", { children: solidgateCheckoutDialogStyles })] }));
352
+ }
353
+ const solidgateCheckoutDialogStyles = `
354
+ .solidgate-checkout-overlay {
355
+ position: fixed;
356
+ inset: 0;
357
+ z-index: 100;
358
+ box-sizing: border-box;
359
+ display: flex;
360
+ align-items: center;
361
+ justify-content: center;
362
+ overflow: hidden;
363
+ padding: 16px;
364
+ background: rgb(17 24 39 / 60%);
365
+ backdrop-filter: blur(4px);
366
+ }
367
+
368
+ .solidgate-checkout-dialog {
369
+ box-sizing: border-box;
370
+ width: min(100%, 512px);
371
+ max-height: calc(100svh - 32px);
372
+ overflow-y: auto;
373
+ border: 1px solid var(--color-border, #d1d5db);
374
+ border-radius: 16px;
375
+ background: var(--color-surface, #fff);
376
+ padding: 20px;
377
+ color: var(--color-text, #111827);
378
+ box-shadow: 0 24px 80px rgb(17 24 39 / 22%);
379
+ }
380
+
381
+ .solidgate-checkout-header {
382
+ display: flex;
383
+ align-items: center;
384
+ justify-content: space-between;
385
+ gap: 16px;
386
+ margin-bottom: 16px;
387
+ }
388
+
389
+ .solidgate-checkout-title {
390
+ margin: 0;
391
+ color: var(--color-text, #111827);
392
+ font-size: 18px;
393
+ font-weight: 600;
394
+ line-height: 1.3;
395
+ }
396
+
397
+ .solidgate-checkout-close {
398
+ width: 36px;
399
+ height: 36px;
400
+ flex: none;
401
+ border: 1px solid var(--color-border, #d1d5db);
402
+ border-radius: 8px;
403
+ background: var(--color-bg, #f9fafb);
404
+ color: var(--color-text, #111827);
405
+ font-size: 22px;
406
+ line-height: 1;
407
+ cursor: pointer;
408
+ }
409
+
410
+ .solidgate-checkout-close:hover {
411
+ background: var(--color-accent-soft, #eef2ff);
412
+ }
413
+
414
+ .solidgate-checkout-email-form,
415
+ .solidgate-checkout-email-label,
416
+ .solidgate-checkout-wallets {
417
+ display: grid;
418
+ }
419
+
420
+ .solidgate-checkout-email-form {
421
+ gap: 16px;
422
+ }
423
+
424
+ .solidgate-checkout-email-label {
425
+ gap: 8px;
426
+ color: var(--color-text, #111827);
427
+ font-size: 14px;
428
+ font-weight: 500;
429
+ }
430
+
431
+ .solidgate-checkout-email-input {
432
+ box-sizing: border-box;
433
+ width: 100%;
434
+ min-height: 44px;
435
+ border: 1px solid var(--color-border, #d1d5db);
436
+ border-radius: 8px;
437
+ background: var(--color-bg, #fff);
438
+ padding: 8px 12px;
439
+ color: var(--color-text, #111827);
440
+ font: inherit;
441
+ }
442
+
443
+ .solidgate-checkout-email-input::placeholder,
444
+ .solidgate-checkout-status,
445
+ .solidgate-checkout-status-text {
446
+ color: var(--color-text-muted, #6b7280);
447
+ }
448
+
449
+ .solidgate-checkout-email-input:focus-visible,
450
+ .solidgate-checkout-close:focus-visible,
451
+ .solidgate-checkout-action:focus-visible {
452
+ outline: 2px solid var(--color-accent, #3f51b5);
453
+ outline-offset: 2px;
454
+ }
455
+
456
+ .solidgate-checkout-alert {
457
+ margin: 0;
458
+ color: var(--color-danger, #b91c1c);
459
+ font-size: 14px;
460
+ }
461
+
462
+ .solidgate-checkout-action {
463
+ box-sizing: border-box;
464
+ width: 100%;
465
+ min-height: 44px;
466
+ border: 1px solid var(--color-accent, #3f51b5);
467
+ border-radius: 8px;
468
+ background: var(--color-accent, #3f51b5);
469
+ padding: 8px 16px;
470
+ color: var(--color-primary-text, #fff);
471
+ font: inherit;
472
+ font-weight: 600;
473
+ cursor: pointer;
474
+ }
475
+
476
+ .solidgate-checkout-action:disabled {
477
+ cursor: not-allowed;
478
+ opacity: 0.6;
479
+ }
480
+
481
+ .solidgate-checkout-action--spaced {
482
+ margin-top: 16px;
483
+ }
484
+
485
+ .solidgate-checkout-wallets {
486
+ gap: 12px;
487
+ margin-bottom: 12px;
488
+ }
489
+
490
+ .solidgate-checkout-payment[hidden] {
491
+ display: none;
492
+ }
493
+
494
+ .solidgate-checkout-status {
495
+ margin-top: 12px;
496
+ border: 1px solid var(--color-border, #d1d5db);
497
+ border-radius: 12px;
498
+ background: var(--color-bg, #f9fafb);
499
+ padding: 16px;
500
+ font-size: 14px;
501
+ }
502
+
503
+ .solidgate-checkout-status p,
504
+ .solidgate-checkout-status-text {
505
+ margin: 0;
350
506
  }
507
+ `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/payments",
3
- "version": "0.7.11",
3
+ "version": "0.7.13",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/The-Solid-Grove/funnelsgrove.git",