@easypayment/medusa-paypal-ui 1.0.50 → 1.0.51

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.d.cts CHANGED
@@ -1,4 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import React from 'react';
3
2
 
4
3
  type PayPalConfig = {
@@ -38,15 +37,7 @@ type HttpOptions = {
38
37
  publishableApiKey?: string;
39
38
  };
40
39
 
41
- /**
42
- * True when an error is a Next.js navigation signal (`redirect()` / `notFound()`
43
- * from a server action). These MUST be re-thrown / ignored, never shown as an
44
- * error — a successful `placeOrder()` redirect surfaces as one of these.
45
- */
46
- declare function isNextRedirectError(e: unknown): boolean;
47
- declare function markPaymentComplete(baseUrl: string, cartId: string, publishableApiKey?: string): Promise<{
48
- ok: boolean;
49
- } & Record<string, any>>;
40
+ declare function markPaymentComplete(baseUrl: string, cartId: string, publishableApiKey?: string): Promise<Record<string, any>>;
50
41
  declare function createPayPalStoreApi(opts: HttpOptions): {
51
42
  getConfig(cartId?: string, signal?: AbortSignal): Promise<PayPalConfig>;
52
43
  getSettings(): Promise<PayPalSettingsResponse>;
@@ -73,11 +64,11 @@ declare function PayPalProvider(props: {
73
64
  intent?: "capture" | "authorize";
74
65
  disableFunding?: string;
75
66
  children: React.ReactNode;
76
- }): react_jsx_runtime.JSX.Element;
67
+ }): React.JSX.Element;
77
68
 
78
69
  declare function PayPalCurrencyNotice({ config }: {
79
70
  config: PayPalConfig;
80
- }): react_jsx_runtime.JSX.Element | null;
71
+ }): React.JSX.Element | null;
81
72
 
82
73
  declare function PayPalSmartButtons(props: {
83
74
  baseUrl: string;
@@ -86,7 +77,7 @@ declare function PayPalSmartButtons(props: {
86
77
  config: PayPalConfig;
87
78
  onPaid?: (result: Record<string, unknown>) => void;
88
79
  onError?: (message: string) => void;
89
- }): react_jsx_runtime.JSX.Element | null;
80
+ }): React.JSX.Element | null;
90
81
 
91
82
  declare function PayPalAdvancedCard(props: {
92
83
  baseUrl: string;
@@ -95,7 +86,7 @@ declare function PayPalAdvancedCard(props: {
95
86
  config: PayPalConfig;
96
87
  onPaid?: (result: Record<string, unknown>) => void;
97
88
  onError?: (message: string) => void;
98
- }): react_jsx_runtime.JSX.Element | null;
89
+ }): React.JSX.Element | null;
99
90
 
100
91
  type MedusaNextPayPalAdapterProps = {
101
92
  cartId: string;
@@ -110,7 +101,7 @@ type MedusaNextPayPalAdapterProps = {
110
101
  onError?: (message: string) => void;
111
102
  onPaid?: (result: unknown) => void;
112
103
  };
113
- declare function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps): react_jsx_runtime.JSX.Element | null;
104
+ declare function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps): React.JSX.Element | null;
114
105
 
115
106
  declare const PAYPAL_WALLET_PROVIDER_ID: "pp_paypal_paypal";
116
107
  declare const PAYPAL_CARD_PROVIDER_ID: "pp_paypal_card_paypal_card";
@@ -125,7 +116,7 @@ type PayPalPaymentSectionProps = {
125
116
  onError?: (message: string) => void;
126
117
  onPaid?: (result: unknown) => void;
127
118
  };
128
- declare function PayPalPaymentSection({ cartId, selectedProviderId, baseUrl, publishableApiKey, sessionLoading, onSuccess, onError, onPaid, }: PayPalPaymentSectionProps): react_jsx_runtime.JSX.Element | null;
119
+ declare function PayPalPaymentSection({ cartId, selectedProviderId, baseUrl, publishableApiKey, sessionLoading, onSuccess, onError, onPaid, }: PayPalPaymentSectionProps): React.JSX.Element | null;
129
120
 
130
121
  type Args = {
131
122
  baseUrl: string;
@@ -142,4 +133,4 @@ type Result = {
142
133
  };
143
134
  declare function usePayPalPaymentMethods({ baseUrl, publishableApiKey, cartId, enabled, }: Args): Result;
144
135
 
145
- export { MedusaNextPayPalAdapter, type MedusaNextPayPalAdapterProps, PAYPAL_CARD_PROVIDER_ID, PAYPAL_WALLET_PROVIDER_ID, PayPalAdvancedCard, type PayPalConfig, PayPalCurrencyNotice, PayPalPaymentSection, type PayPalPaymentSectionProps, PayPalProvider, type PayPalSettingsResponse, PayPalSmartButtons, createPayPalStoreApi, isNextRedirectError, isPayPalProviderId, markPaymentComplete, usePayPalConfig, usePayPalPaymentMethods };
136
+ export { MedusaNextPayPalAdapter, type MedusaNextPayPalAdapterProps, PAYPAL_CARD_PROVIDER_ID, PAYPAL_WALLET_PROVIDER_ID, PayPalAdvancedCard, type PayPalConfig, PayPalCurrencyNotice, PayPalPaymentSection, type PayPalPaymentSectionProps, PayPalProvider, type PayPalSettingsResponse, PayPalSmartButtons, createPayPalStoreApi, isPayPalProviderId, markPaymentComplete, usePayPalConfig, usePayPalPaymentMethods };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import React from 'react';
3
2
 
4
3
  type PayPalConfig = {
@@ -38,15 +37,7 @@ type HttpOptions = {
38
37
  publishableApiKey?: string;
39
38
  };
40
39
 
41
- /**
42
- * True when an error is a Next.js navigation signal (`redirect()` / `notFound()`
43
- * from a server action). These MUST be re-thrown / ignored, never shown as an
44
- * error — a successful `placeOrder()` redirect surfaces as one of these.
45
- */
46
- declare function isNextRedirectError(e: unknown): boolean;
47
- declare function markPaymentComplete(baseUrl: string, cartId: string, publishableApiKey?: string): Promise<{
48
- ok: boolean;
49
- } & Record<string, any>>;
40
+ declare function markPaymentComplete(baseUrl: string, cartId: string, publishableApiKey?: string): Promise<Record<string, any>>;
50
41
  declare function createPayPalStoreApi(opts: HttpOptions): {
51
42
  getConfig(cartId?: string, signal?: AbortSignal): Promise<PayPalConfig>;
52
43
  getSettings(): Promise<PayPalSettingsResponse>;
@@ -73,11 +64,11 @@ declare function PayPalProvider(props: {
73
64
  intent?: "capture" | "authorize";
74
65
  disableFunding?: string;
75
66
  children: React.ReactNode;
76
- }): react_jsx_runtime.JSX.Element;
67
+ }): React.JSX.Element;
77
68
 
78
69
  declare function PayPalCurrencyNotice({ config }: {
79
70
  config: PayPalConfig;
80
- }): react_jsx_runtime.JSX.Element | null;
71
+ }): React.JSX.Element | null;
81
72
 
82
73
  declare function PayPalSmartButtons(props: {
83
74
  baseUrl: string;
@@ -86,7 +77,7 @@ declare function PayPalSmartButtons(props: {
86
77
  config: PayPalConfig;
87
78
  onPaid?: (result: Record<string, unknown>) => void;
88
79
  onError?: (message: string) => void;
89
- }): react_jsx_runtime.JSX.Element | null;
80
+ }): React.JSX.Element | null;
90
81
 
91
82
  declare function PayPalAdvancedCard(props: {
92
83
  baseUrl: string;
@@ -95,7 +86,7 @@ declare function PayPalAdvancedCard(props: {
95
86
  config: PayPalConfig;
96
87
  onPaid?: (result: Record<string, unknown>) => void;
97
88
  onError?: (message: string) => void;
98
- }): react_jsx_runtime.JSX.Element | null;
89
+ }): React.JSX.Element | null;
99
90
 
100
91
  type MedusaNextPayPalAdapterProps = {
101
92
  cartId: string;
@@ -110,7 +101,7 @@ type MedusaNextPayPalAdapterProps = {
110
101
  onError?: (message: string) => void;
111
102
  onPaid?: (result: unknown) => void;
112
103
  };
113
- declare function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps): react_jsx_runtime.JSX.Element | null;
104
+ declare function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps): React.JSX.Element | null;
114
105
 
115
106
  declare const PAYPAL_WALLET_PROVIDER_ID: "pp_paypal_paypal";
116
107
  declare const PAYPAL_CARD_PROVIDER_ID: "pp_paypal_card_paypal_card";
@@ -125,7 +116,7 @@ type PayPalPaymentSectionProps = {
125
116
  onError?: (message: string) => void;
126
117
  onPaid?: (result: unknown) => void;
127
118
  };
128
- declare function PayPalPaymentSection({ cartId, selectedProviderId, baseUrl, publishableApiKey, sessionLoading, onSuccess, onError, onPaid, }: PayPalPaymentSectionProps): react_jsx_runtime.JSX.Element | null;
119
+ declare function PayPalPaymentSection({ cartId, selectedProviderId, baseUrl, publishableApiKey, sessionLoading, onSuccess, onError, onPaid, }: PayPalPaymentSectionProps): React.JSX.Element | null;
129
120
 
130
121
  type Args = {
131
122
  baseUrl: string;
@@ -142,4 +133,4 @@ type Result = {
142
133
  };
143
134
  declare function usePayPalPaymentMethods({ baseUrl, publishableApiKey, cartId, enabled, }: Args): Result;
144
135
 
145
- export { MedusaNextPayPalAdapter, type MedusaNextPayPalAdapterProps, PAYPAL_CARD_PROVIDER_ID, PAYPAL_WALLET_PROVIDER_ID, PayPalAdvancedCard, type PayPalConfig, PayPalCurrencyNotice, PayPalPaymentSection, type PayPalPaymentSectionProps, PayPalProvider, type PayPalSettingsResponse, PayPalSmartButtons, createPayPalStoreApi, isNextRedirectError, isPayPalProviderId, markPaymentComplete, usePayPalConfig, usePayPalPaymentMethods };
136
+ export { MedusaNextPayPalAdapter, type MedusaNextPayPalAdapterProps, PAYPAL_CARD_PROVIDER_ID, PAYPAL_WALLET_PROVIDER_ID, PayPalAdvancedCard, type PayPalConfig, PayPalCurrencyNotice, PayPalPaymentSection, type PayPalPaymentSectionProps, PayPalProvider, type PayPalSettingsResponse, PayPalSmartButtons, createPayPalStoreApi, isPayPalProviderId, markPaymentComplete, usePayPalConfig, usePayPalPaymentMethods };
package/dist/index.mjs CHANGED
@@ -13,7 +13,6 @@ function toHeaderRecord(headers) {
13
13
  }
14
14
  return { ...headers };
15
15
  }
16
- var DEFAULT_TIMEOUT_MS = 3e4;
17
16
  function createHttpClient(opts) {
18
17
  const base = opts.baseUrl.replace(/\/+$/, "");
19
18
  async function request(path, init) {
@@ -25,33 +24,8 @@ function createHttpClient(opts) {
25
24
  if (opts.publishableApiKey) {
26
25
  headers["x-publishable-api-key"] = opts.publishableApiKey;
27
26
  }
28
- const controller = new AbortController();
29
- let timedOut = false;
30
- const timer = setTimeout(() => {
31
- timedOut = true;
32
- controller.abort();
33
- }, DEFAULT_TIMEOUT_MS);
34
- const callerSignal = init?.signal;
35
- if (callerSignal) {
36
- if (callerSignal.aborted) {
37
- controller.abort();
38
- } else {
39
- callerSignal.addEventListener("abort", () => controller.abort(), { once: true });
40
- }
41
- }
42
- let res;
43
- let text;
44
- try {
45
- res = await fetch(url, { ...init, headers, credentials: "include", signal: controller.signal });
46
- text = await res.text().catch(() => "");
47
- } catch (e) {
48
- if (timedOut) {
49
- throw new Error("[PayPal] Request timed out. Please check your connection and try again.");
50
- }
51
- throw e;
52
- } finally {
53
- clearTimeout(timer);
54
- }
27
+ const res = await fetch(url, { ...init, headers, credentials: "include" });
28
+ const text = await res.text().catch(() => "");
55
29
  if (!res.ok) {
56
30
  if (res.status === 401) {
57
31
  throw new Error(
@@ -63,21 +37,9 @@ function createHttpClient(opts) {
63
37
  "[PayPal] Forbidden (403) \u2014 this request is not allowed. Check your CORS and API key settings."
64
38
  );
65
39
  }
66
- let parsed = null;
67
- try {
68
- parsed = text ? JSON.parse(text) : null;
69
- } catch {
70
- parsed = null;
71
- }
72
- const backendMessage = typeof parsed?.message === "string" ? parsed.message : "";
73
- const requestId = typeof parsed?.request_id === "string" ? parsed.request_id : "";
74
- if (res.status >= 500) {
75
- console.error(`[PayPal] ${path} failed (${res.status})`, text.slice(0, 1e3));
76
- throw new Error(
77
- `Payment service error${requestId ? ` (ref ${requestId})` : ""}. Please try again or contact support.`
78
- );
79
- }
80
- throw new Error(backendMessage || `Request failed (${res.status})`);
40
+ throw new Error(
41
+ text.slice(0, 500).replace(/<[^>]*>/g, "") || `Request failed (${res.status})`
42
+ );
81
43
  }
82
44
  if (!text) {
83
45
  throw new Error(`[PayPal] Empty response body from ${path} (${res.status})`);
@@ -98,13 +60,6 @@ function createHttpClient(opts) {
98
60
  }
99
61
 
100
62
  // src/client/paypal.ts
101
- function isNextRedirectError(e) {
102
- if (!e || typeof e !== "object") {
103
- return false;
104
- }
105
- const digest = e.digest;
106
- return typeof digest === "string" && (digest.startsWith("NEXT_REDIRECT") || digest === "NEXT_NOT_FOUND");
107
- }
108
63
  async function markPaymentComplete(baseUrl, cartId, publishableApiKey) {
109
64
  try {
110
65
  const resp = await fetch(`${baseUrl.replace(/\/$/, "")}/store/paypal-complete`, {
@@ -117,14 +72,10 @@ async function markPaymentComplete(baseUrl, cartId, publishableApiKey) {
117
72
  credentials: "include"
118
73
  });
119
74
  const data = await resp.json().catch(() => ({}));
120
- if (!resp.ok) {
121
- console.warn("[PayPal] paypal-complete returned", resp.status, data);
122
- return { ok: false, ...data || {} };
123
- }
124
- return { ok: true, ...data || {} };
75
+ return data || {};
125
76
  } catch (e) {
126
77
  console.warn("[PayPal] paypal-complete call failed:", e);
127
- return { ok: false };
78
+ return {};
128
79
  }
129
80
  }
130
81
  function createPayPalStoreApi(opts) {
@@ -259,7 +210,7 @@ function PayPalCurrencyNotice({ config }) {
259
210
 
260
211
  // src/components/PayPalSmartButtons.tsx
261
212
  import { useMemo as useMemo3, useState as useState2 } from "react";
262
- import { PayPalButtons } from "@paypal/react-paypal-js";
213
+ import { PayPalButtons, usePayPalScriptReducer } from "@paypal/react-paypal-js";
263
214
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
264
215
  var SPIN_STYLE = `@keyframes _pp_spin { to { transform: rotate(360deg) } }`;
265
216
  var BUTTON_WIDTH_MAP = {
@@ -276,6 +227,7 @@ function PayPalSmartButtons(props) {
276
227
  );
277
228
  const [error, setError] = useState2(null);
278
229
  const [processing, setProcessing] = useState2(false);
230
+ const [{ isPending, isResolved }] = usePayPalScriptReducer();
279
231
  if (!config.currency_supported) return null;
280
232
  const containerWidth = BUTTON_WIDTH_MAP[config.button_width ?? "responsive"] ?? "100%";
281
233
  return /* @__PURE__ */ jsxs2("div", { style: { width: containerWidth, position: "relative" }, children: [
@@ -317,7 +269,40 @@ function PayPalSmartButtons(props) {
317
269
  ]
318
270
  }
319
271
  ),
320
- config.environment === "sandbox" && /* @__PURE__ */ jsxs2(
272
+ isPending && /* @__PURE__ */ jsxs2(
273
+ "div",
274
+ {
275
+ style: {
276
+ display: "flex",
277
+ alignItems: "center",
278
+ justifyContent: "center",
279
+ gap: 10,
280
+ padding: "18px 16px",
281
+ background: "#f9fafb",
282
+ border: "1px solid #e5e7eb",
283
+ borderRadius: 8,
284
+ minHeight: 55
285
+ },
286
+ children: [
287
+ /* @__PURE__ */ jsx3(
288
+ "div",
289
+ {
290
+ style: {
291
+ width: 22,
292
+ height: 22,
293
+ borderRadius: "50%",
294
+ border: "2.5px solid #e5e7eb",
295
+ borderTopColor: "#0070ba",
296
+ animation: "_pp_spin .7s linear infinite",
297
+ flexShrink: 0
298
+ }
299
+ }
300
+ ),
301
+ /* @__PURE__ */ jsx3("div", { style: { fontSize: 13, fontWeight: 500, color: "#6b7280" }, children: "Loading PayPal\u2026" })
302
+ ]
303
+ }
304
+ ),
305
+ config.environment === "sandbox" && isResolved && /* @__PURE__ */ jsxs2(
321
306
  "div",
322
307
  {
323
308
  style: {
@@ -355,9 +340,10 @@ function PayPalSmartButtons(props) {
355
340
  ]
356
341
  }
357
342
  ),
358
- /* @__PURE__ */ jsx3(
343
+ isResolved && /* @__PURE__ */ jsx3(
359
344
  PayPalButtons,
360
345
  {
346
+ forceReRender: [config.currency, config.intent, cartId],
361
347
  style: {
362
348
  layout: "vertical",
363
349
  color: config.button_color,
@@ -478,8 +464,7 @@ var labelStyle = {
478
464
  function SubmitButton({
479
465
  disabled,
480
466
  label,
481
- onSubmit,
482
- onSubmitError
467
+ onSubmit
483
468
  }) {
484
469
  const { cardFieldsForm } = usePayPalCardFields();
485
470
  const isDisabled = disabled || !cardFieldsForm;
@@ -490,14 +475,7 @@ function SubmitButton({
490
475
  disabled: isDisabled,
491
476
  onClick: () => {
492
477
  onSubmit();
493
- const submitted = cardFieldsForm?.submit();
494
- if (submitted && typeof submitted.catch === "function") {
495
- submitted.catch((e) => {
496
- onSubmitError(
497
- e instanceof Error ? e.message : "Card payment failed. Please try again."
498
- );
499
- });
500
- }
478
+ cardFieldsForm?.submit();
501
479
  },
502
480
  style: {
503
481
  width: "100%",
@@ -729,11 +707,6 @@ function PayPalAdvancedCard(props) {
729
707
  onSubmit: () => {
730
708
  setError(null);
731
709
  setSubmitting(true);
732
- },
733
- onSubmitError: (msg) => {
734
- setError(msg);
735
- onError?.(msg);
736
- setSubmitting(false);
737
710
  }
738
711
  }
739
712
  ),
@@ -848,14 +821,9 @@ function MedusaNextPayPalAdapter(props) {
848
821
  const handlePaid = useCallback(
849
822
  (captureResult) => {
850
823
  onPaid?.(captureResult);
851
- Promise.resolve(onSuccess?.(cartId)).catch((e) => {
852
- if (isNextRedirectError(e)) return;
853
- onError?.(
854
- e instanceof Error ? e.message : "Your payment was taken but the order could not be finalized. Please contact support before paying again."
855
- );
856
- });
824
+ onSuccess?.(cartId);
857
825
  },
858
- [cartId, onPaid, onSuccess, onError]
826
+ [cartId, onPaid, onSuccess]
859
827
  );
860
828
  if (!shouldRender) return null;
861
829
  if (loading) return /* @__PURE__ */ jsx5(PayPalLoadingCard, {});
@@ -1021,14 +989,9 @@ function PayPalPaymentSection({
1021
989
  const handlePaid = useCallback2(
1022
990
  (captureResult) => {
1023
991
  onPaid?.(captureResult);
1024
- Promise.resolve(onSuccess?.(cartId)).catch((e) => {
1025
- if (isNextRedirectError(e)) return;
1026
- onError?.(
1027
- e instanceof Error ? e.message : "Your payment was taken but the order could not be finalized. Please contact support before paying again."
1028
- );
1029
- });
992
+ onSuccess?.(cartId);
1030
993
  },
1031
- [cartId, onPaid, onSuccess, onError]
994
+ [cartId, onPaid, onSuccess]
1032
995
  );
1033
996
  if (!shouldRender) return null;
1034
997
  if (sessionLoading) return /* @__PURE__ */ jsx6(SessionInitCard, {});
@@ -1165,7 +1128,6 @@ export {
1165
1128
  PayPalProvider,
1166
1129
  PayPalSmartButtons,
1167
1130
  createPayPalStoreApi,
1168
- isNextRedirectError,
1169
1131
  isPayPalProviderId,
1170
1132
  markPaymentComplete,
1171
1133
  usePayPalConfig,