@easypayment/medusa-paypal-ui 1.0.51 → 1.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +444 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.mjs +452 -93
- package/dist/index.mjs.map +1 -1
- package/dist/order.cjs +20 -7
- package/dist/order.cjs.map +1 -1
- package/dist/order.mjs +20 -7
- package/dist/order.mjs.map +1 -1
- package/package.json +11 -1
- package/src/adapters/MedusaNextPayPalAdapter.tsx +5 -2
- package/src/client/http.ts +18 -1
- package/src/client/paypal.ts +7 -17
- package/src/components/PayPalAdvancedCard.tsx +177 -29
- package/src/components/PayPalCurrencyNotice.tsx +1 -1
- package/src/components/PayPalPaymentSection.tsx +7 -2
- package/src/components/PayPalProvider.tsx +1 -1
- package/src/components/PayPalSmartButtons.tsx +133 -30
- package/src/hooks/usePayPalConfig.ts +13 -4
- package/src/hooks/usePayPalPaymentMethods.ts +14 -4
- package/src/index.ts +1 -0
- package/src/order.ts +20 -7
- package/src/utils/next-errors.ts +17 -0
- package/src/utils/processing-overlay.ts +55 -0
|
@@ -19,9 +19,18 @@ type Result = {
|
|
|
19
19
|
loading: boolean
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
const MAX_CACHE_ENTRIES = 50
|
|
22
23
|
const _cache = new Map<string, { result: Result; at: number }>()
|
|
23
24
|
const CACHE_TTL = 5 * 60 * 1000
|
|
24
25
|
|
|
26
|
+
function cacheSet(key: string, value: { result: Result; at: number }) {
|
|
27
|
+
if (_cache.size >= MAX_CACHE_ENTRIES) {
|
|
28
|
+
const oldest = _cache.keys().next().value
|
|
29
|
+
if (oldest !== undefined) _cache.delete(oldest)
|
|
30
|
+
}
|
|
31
|
+
_cache.set(key, value)
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
function cacheKey(baseUrl: string, cartId?: string) {
|
|
26
35
|
return `ppm::${baseUrl}::${cartId ?? ""}`
|
|
27
36
|
}
|
|
@@ -90,13 +99,14 @@ export function usePayPalPaymentMethods({
|
|
|
90
99
|
loading: false,
|
|
91
100
|
}
|
|
92
101
|
|
|
93
|
-
|
|
102
|
+
cacheSet(k, { result: next, at: Date.now() })
|
|
94
103
|
setResult(next)
|
|
95
|
-
} catch (e:
|
|
96
|
-
|
|
104
|
+
} catch (e: unknown) {
|
|
105
|
+
const msg = e instanceof Error ? e.message : ""
|
|
106
|
+
if (e instanceof Error && e.name === "AbortError") return
|
|
97
107
|
if (!mounted || id !== fetchIdRef.current) return
|
|
98
108
|
|
|
99
|
-
if (
|
|
109
|
+
if (msg.includes("403") || msg.includes("Forbidden")) {
|
|
100
110
|
const disabled: Result = {
|
|
101
111
|
...DEFAULT_RESULT,
|
|
102
112
|
paypalEnabled: false,
|
package/src/index.ts
CHANGED
|
@@ -8,3 +8,4 @@ export * from "./components/PayPalAdvancedCard"
|
|
|
8
8
|
export * from "./adapters/MedusaNextPayPalAdapter"
|
|
9
9
|
export * from "./components/PayPalPaymentSection"
|
|
10
10
|
export * from "./hooks/usePayPalPaymentMethods"
|
|
11
|
+
export { showProcessingOverlay, hideProcessingOverlay } from "./utils/processing-overlay"
|
package/src/order.ts
CHANGED
|
@@ -101,13 +101,26 @@ export async function fetchPayPalConfig(opts: {
|
|
|
101
101
|
return {}
|
|
102
102
|
}
|
|
103
103
|
try {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
const timeoutMs = 30_000
|
|
105
|
+
let effectiveSignal = signal
|
|
106
|
+
let timeoutId: ReturnType<typeof setTimeout> | undefined
|
|
107
|
+
if (!signal) {
|
|
108
|
+
const controller = new AbortController()
|
|
109
|
+
timeoutId = setTimeout(() => controller.abort(), timeoutMs)
|
|
110
|
+
effectiveSignal = controller.signal
|
|
111
|
+
}
|
|
112
|
+
let res: Response
|
|
113
|
+
try {
|
|
114
|
+
res = await fetch(`${baseUrl.replace(/\/$/, "")}/store/paypal/config`, {
|
|
115
|
+
headers: {
|
|
116
|
+
accept: "application/json",
|
|
117
|
+
...(publishableApiKey ? { "x-publishable-api-key": publishableApiKey } : {}),
|
|
118
|
+
},
|
|
119
|
+
signal: effectiveSignal,
|
|
120
|
+
})
|
|
121
|
+
} finally {
|
|
122
|
+
if (timeoutId !== undefined) clearTimeout(timeoutId)
|
|
123
|
+
}
|
|
111
124
|
if (!res.ok) {
|
|
112
125
|
return {}
|
|
113
126
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect Next.js router errors (redirect / notFound) that must be re-thrown.
|
|
3
|
+
*
|
|
4
|
+
* Next.js implements redirect() and notFound() by throwing special errors with
|
|
5
|
+
* a `digest` property starting with "NEXT_REDIRECT" or "NEXT_NOT_FOUND".
|
|
6
|
+
* Catching these in user-land try/catch blocks prevents the navigation from
|
|
7
|
+
* happening. Because this package can't import from `next` (it's a peer dep),
|
|
8
|
+
* we detect them by duck-typing the digest.
|
|
9
|
+
*/
|
|
10
|
+
export function isNextRouterError(e: unknown): boolean {
|
|
11
|
+
if (typeof e !== "object" || e === null || !("digest" in e)) return false
|
|
12
|
+
const digest = (e as { digest: unknown }).digest
|
|
13
|
+
return (
|
|
14
|
+
typeof digest === "string" &&
|
|
15
|
+
(digest.startsWith("NEXT_REDIRECT") || digest.startsWith("NEXT_NOT_FOUND"))
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const OVERLAY_ID = "__pp_processing_overlay"
|
|
2
|
+
|
|
3
|
+
export function showProcessingOverlay() {
|
|
4
|
+
if (typeof document === "undefined") return
|
|
5
|
+
if (document.getElementById(OVERLAY_ID)) return
|
|
6
|
+
|
|
7
|
+
const overlay = document.createElement("div")
|
|
8
|
+
overlay.id = OVERLAY_ID
|
|
9
|
+
overlay.setAttribute("role", "status")
|
|
10
|
+
overlay.setAttribute("aria-label", "Processing payment")
|
|
11
|
+
|
|
12
|
+
overlay.innerHTML = `
|
|
13
|
+
<style>
|
|
14
|
+
@keyframes _pp_spin { to { transform: rotate(360deg) } }
|
|
15
|
+
@keyframes _pp_progress { 0% { transform: translateX(-100%) } 100% { transform: translateX(350%) } }
|
|
16
|
+
</style>
|
|
17
|
+
<div style="position:relative;width:56px;height:56px">
|
|
18
|
+
<div style="position:absolute;inset:0;border-radius:50%;border:3px solid #e5e7eb"></div>
|
|
19
|
+
<div style="position:absolute;inset:0;border-radius:50%;border:3px solid transparent;border-top-color:#0070ba;animation:_pp_spin .8s linear infinite"></div>
|
|
20
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="#0070ba" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"
|
|
21
|
+
style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:24px;height:24px">
|
|
22
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
|
23
|
+
</svg>
|
|
24
|
+
</div>
|
|
25
|
+
<div style="text-align:center">
|
|
26
|
+
<div style="font-size:18px;font-weight:600;color:#111827;letter-spacing:-0.01em">Processing your payment</div>
|
|
27
|
+
<div style="font-size:14px;color:#6b7280;margin-top:6px;line-height:1.5">
|
|
28
|
+
This may take a few moments. Please do not close<br>or refresh this page.
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div style="width:200px;height:3px;background:#e5e7eb;border-radius:3px;overflow:hidden;margin-top:4px">
|
|
32
|
+
<div style="width:40%;height:100%;background:linear-gradient(90deg,#0070ba,#003087);border-radius:3px;animation:_pp_progress 1.5s ease-in-out infinite"></div>
|
|
33
|
+
</div>
|
|
34
|
+
`
|
|
35
|
+
|
|
36
|
+
Object.assign(overlay.style, {
|
|
37
|
+
position: "fixed",
|
|
38
|
+
inset: "0",
|
|
39
|
+
zIndex: "99999",
|
|
40
|
+
background: "rgba(255,255,255,0.96)",
|
|
41
|
+
display: "flex",
|
|
42
|
+
flexDirection: "column",
|
|
43
|
+
alignItems: "center",
|
|
44
|
+
justifyContent: "center",
|
|
45
|
+
gap: "20px",
|
|
46
|
+
fontFamily: "-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif",
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
document.body.appendChild(overlay)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function hideProcessingOverlay() {
|
|
53
|
+
if (typeof document === "undefined") return
|
|
54
|
+
document.getElementById(OVERLAY_ID)?.remove()
|
|
55
|
+
}
|