@easypayment/medusa-paypal-ui 1.0.39 → 1.0.41

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
@@ -47,13 +47,13 @@ declare function createPayPalStoreApi(opts: HttpOptions): {
47
47
  captureOrder(cartId: string, orderId: string): Promise<Record<string, unknown>>;
48
48
  };
49
49
 
50
- type Args = {
50
+ type Args$1 = {
51
51
  baseUrl: string;
52
52
  publishableApiKey?: string;
53
53
  cartId?: string;
54
54
  enabled?: boolean;
55
55
  };
56
- declare function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled, }: Args): {
56
+ declare function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled, }: Args$1): {
57
57
  config: PayPalConfig | null;
58
58
  loading: boolean;
59
59
  error: string | null;
@@ -111,4 +111,71 @@ type MedusaNextPayPalAdapterProps = {
111
111
  };
112
112
  declare function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps): react_jsx_runtime.JSX.Element | null;
113
113
 
114
- export { MedusaNextPayPalAdapter, type MedusaNextPayPalAdapterProps, PayPalAdvancedCard, type PayPalConfig, PayPalCurrencyNotice, PayPalProvider, type PayPalSettingsResponse, PayPalSmartButtons, createPayPalStoreApi, usePayPalConfig };
114
+ declare const PAYPAL_WALLET_PROVIDER_ID: "pp_paypal_paypal";
115
+ declare const PAYPAL_CARD_PROVIDER_ID: "pp_paypal_card_paypal_card";
116
+ /**
117
+ * Returns true when the given provider ID is a PayPal provider.
118
+ * Use this to disable the storefront's "Continue to review" button.
119
+ *
120
+ * @example
121
+ * disabled={isPayPalProviderId(selectedPaymentMethod)}
122
+ */
123
+ declare function isPayPalProviderId(id?: string | null): boolean;
124
+ type PayPalPaymentSectionProps = {
125
+ cartId: string;
126
+ selectedProviderId: string | null | undefined;
127
+ baseUrl: string;
128
+ publishableApiKey?: string;
129
+ /**
130
+ * Whether a PayPal session is currently being initiated by the storefront
131
+ * (i.e. the `initiatePaymentSession()` call is in-flight).
132
+ * When true, the component shows a "Setting up payment…" spinner instead
133
+ * of the PayPal buttons.
134
+ *
135
+ * @example
136
+ * const [paypalLoading, setPaypalLoading] = useState(false)
137
+ *
138
+ * const setPaymentMethod = async (method: string) => {
139
+ * if (isPayPalProviderId(method)) setPaypalLoading(true)
140
+ * try { await initiatePaymentSession(cart, { provider_id: method }) }
141
+ * finally { setPaypalLoading(false) }
142
+ * }
143
+ *
144
+ * <PayPalPaymentSection sessionLoading={paypalLoading} ... />
145
+ */
146
+ sessionLoading?: boolean;
147
+ /**
148
+ * Called after PayPal capture succeeds.
149
+ * You must call placeOrder(cartId) here so the Next.js server action
150
+ * can clear the httpOnly cart cookie.
151
+ */
152
+ onSuccess?: (cartId: string) => void;
153
+ onError?: (message: string) => void;
154
+ /** @deprecated use onSuccess */
155
+ onPaid?: (result: unknown) => void;
156
+ };
157
+ /**
158
+ * Drop-in PayPal payment section for Medusa storefronts.
159
+ *
160
+ * Renders nothing when a non-PayPal provider is selected.
161
+ * Shows a spinner while config is loading or the session is being created.
162
+ * Automatically picks Smart Buttons vs Advanced Card based on selectedProviderId.
163
+ */
164
+ declare function PayPalPaymentSection({ cartId, selectedProviderId, baseUrl, publishableApiKey, sessionLoading, onSuccess, onError, onPaid, }: PayPalPaymentSectionProps): react_jsx_runtime.JSX.Element | null;
165
+
166
+ type Args = {
167
+ baseUrl: string;
168
+ publishableApiKey?: string;
169
+ cartId?: string;
170
+ enabled?: boolean;
171
+ };
172
+ type Result = {
173
+ paypalEnabled: boolean;
174
+ paypalTitle: string;
175
+ cardEnabled: boolean;
176
+ cardTitle: string;
177
+ loading: boolean;
178
+ };
179
+ declare function usePayPalPaymentMethods({ baseUrl, publishableApiKey, cartId, enabled, }: Args): Result;
180
+
181
+ 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, usePayPalConfig, usePayPalPaymentMethods };
package/dist/index.d.ts CHANGED
@@ -47,13 +47,13 @@ declare function createPayPalStoreApi(opts: HttpOptions): {
47
47
  captureOrder(cartId: string, orderId: string): Promise<Record<string, unknown>>;
48
48
  };
49
49
 
50
- type Args = {
50
+ type Args$1 = {
51
51
  baseUrl: string;
52
52
  publishableApiKey?: string;
53
53
  cartId?: string;
54
54
  enabled?: boolean;
55
55
  };
56
- declare function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled, }: Args): {
56
+ declare function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled, }: Args$1): {
57
57
  config: PayPalConfig | null;
58
58
  loading: boolean;
59
59
  error: string | null;
@@ -111,4 +111,71 @@ type MedusaNextPayPalAdapterProps = {
111
111
  };
112
112
  declare function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps): react_jsx_runtime.JSX.Element | null;
113
113
 
114
- export { MedusaNextPayPalAdapter, type MedusaNextPayPalAdapterProps, PayPalAdvancedCard, type PayPalConfig, PayPalCurrencyNotice, PayPalProvider, type PayPalSettingsResponse, PayPalSmartButtons, createPayPalStoreApi, usePayPalConfig };
114
+ declare const PAYPAL_WALLET_PROVIDER_ID: "pp_paypal_paypal";
115
+ declare const PAYPAL_CARD_PROVIDER_ID: "pp_paypal_card_paypal_card";
116
+ /**
117
+ * Returns true when the given provider ID is a PayPal provider.
118
+ * Use this to disable the storefront's "Continue to review" button.
119
+ *
120
+ * @example
121
+ * disabled={isPayPalProviderId(selectedPaymentMethod)}
122
+ */
123
+ declare function isPayPalProviderId(id?: string | null): boolean;
124
+ type PayPalPaymentSectionProps = {
125
+ cartId: string;
126
+ selectedProviderId: string | null | undefined;
127
+ baseUrl: string;
128
+ publishableApiKey?: string;
129
+ /**
130
+ * Whether a PayPal session is currently being initiated by the storefront
131
+ * (i.e. the `initiatePaymentSession()` call is in-flight).
132
+ * When true, the component shows a "Setting up payment…" spinner instead
133
+ * of the PayPal buttons.
134
+ *
135
+ * @example
136
+ * const [paypalLoading, setPaypalLoading] = useState(false)
137
+ *
138
+ * const setPaymentMethod = async (method: string) => {
139
+ * if (isPayPalProviderId(method)) setPaypalLoading(true)
140
+ * try { await initiatePaymentSession(cart, { provider_id: method }) }
141
+ * finally { setPaypalLoading(false) }
142
+ * }
143
+ *
144
+ * <PayPalPaymentSection sessionLoading={paypalLoading} ... />
145
+ */
146
+ sessionLoading?: boolean;
147
+ /**
148
+ * Called after PayPal capture succeeds.
149
+ * You must call placeOrder(cartId) here so the Next.js server action
150
+ * can clear the httpOnly cart cookie.
151
+ */
152
+ onSuccess?: (cartId: string) => void;
153
+ onError?: (message: string) => void;
154
+ /** @deprecated use onSuccess */
155
+ onPaid?: (result: unknown) => void;
156
+ };
157
+ /**
158
+ * Drop-in PayPal payment section for Medusa storefronts.
159
+ *
160
+ * Renders nothing when a non-PayPal provider is selected.
161
+ * Shows a spinner while config is loading or the session is being created.
162
+ * Automatically picks Smart Buttons vs Advanced Card based on selectedProviderId.
163
+ */
164
+ declare function PayPalPaymentSection({ cartId, selectedProviderId, baseUrl, publishableApiKey, sessionLoading, onSuccess, onError, onPaid, }: PayPalPaymentSectionProps): react_jsx_runtime.JSX.Element | null;
165
+
166
+ type Args = {
167
+ baseUrl: string;
168
+ publishableApiKey?: string;
169
+ cartId?: string;
170
+ enabled?: boolean;
171
+ };
172
+ type Result = {
173
+ paypalEnabled: boolean;
174
+ paypalTitle: string;
175
+ cardEnabled: boolean;
176
+ cardTitle: string;
177
+ loading: boolean;
178
+ };
179
+ declare function usePayPalPaymentMethods({ baseUrl, publishableApiKey, cartId, enabled, }: Args): Result;
180
+
181
+ 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, usePayPalConfig, usePayPalPaymentMethods };
package/dist/index.mjs CHANGED
@@ -775,6 +775,251 @@ function MedusaNextPayPalAdapter(props) {
775
775
  )
776
776
  ] }, selectedProviderId);
777
777
  }
778
+ var PAYPAL_WALLET_PROVIDER_ID = "pp_paypal_paypal";
779
+ var PAYPAL_CARD_PROVIDER_ID = "pp_paypal_card_paypal_card";
780
+ var PAYPAL_PROVIDER_IDS = [
781
+ PAYPAL_WALLET_PROVIDER_ID,
782
+ PAYPAL_CARD_PROVIDER_ID
783
+ ];
784
+ function isPayPalProviderId(id) {
785
+ if (!id) return false;
786
+ return PAYPAL_PROVIDER_IDS.includes(id);
787
+ }
788
+ var SPIN_STYLE4 = `@keyframes _pp_section_spin { to { transform: rotate(360deg) } }`;
789
+ function SessionInitCard() {
790
+ return /* @__PURE__ */ jsxs(
791
+ "div",
792
+ {
793
+ style: {
794
+ display: "flex",
795
+ alignItems: "center",
796
+ gap: 12,
797
+ padding: "14px 16px",
798
+ marginTop: 8,
799
+ background: "#f9fafb",
800
+ border: "1px solid #e5e7eb",
801
+ borderRadius: 10
802
+ },
803
+ children: [
804
+ /* @__PURE__ */ jsx("style", { children: SPIN_STYLE4 }),
805
+ /* @__PURE__ */ jsx(
806
+ "div",
807
+ {
808
+ style: {
809
+ width: 20,
810
+ height: 20,
811
+ borderRadius: "50%",
812
+ border: "2.5px solid #e5e7eb",
813
+ borderTopColor: "#0070ba",
814
+ animation: "_pp_section_spin .7s linear infinite",
815
+ flexShrink: 0
816
+ }
817
+ }
818
+ ),
819
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 13, fontWeight: 500, color: "#111827" }, children: "Setting up payment\u2026" })
820
+ ]
821
+ }
822
+ );
823
+ }
824
+ function ConfigLoadingCard() {
825
+ return /* @__PURE__ */ jsxs(
826
+ "div",
827
+ {
828
+ style: {
829
+ display: "flex",
830
+ alignItems: "center",
831
+ gap: 12,
832
+ padding: "14px 16px",
833
+ background: "#f9fafb",
834
+ border: "1px solid #e5e7eb",
835
+ borderRadius: 10
836
+ },
837
+ children: [
838
+ /* @__PURE__ */ jsx("style", { children: SPIN_STYLE4 }),
839
+ /* @__PURE__ */ jsx(
840
+ "div",
841
+ {
842
+ style: {
843
+ width: 22,
844
+ height: 22,
845
+ borderRadius: "50%",
846
+ border: "2.5px solid #e5e7eb",
847
+ borderTopColor: "#0070ba",
848
+ animation: "_pp_section_spin .7s linear infinite",
849
+ flexShrink: 0
850
+ }
851
+ }
852
+ ),
853
+ /* @__PURE__ */ jsxs("div", { children: [
854
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 13, fontWeight: 500, color: "#111827" }, children: "Connecting to PayPal\u2026" }),
855
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: "#6b7280", marginTop: 2 }, children: "Setting up secure payment" })
856
+ ] })
857
+ ]
858
+ }
859
+ );
860
+ }
861
+ function ErrorCard({ message }) {
862
+ return /* @__PURE__ */ jsx(
863
+ "div",
864
+ {
865
+ style: {
866
+ padding: "12px 16px",
867
+ background: "#fef2f2",
868
+ border: "1px solid #fecaca",
869
+ borderRadius: 10,
870
+ fontSize: 13,
871
+ color: "#b91c1c"
872
+ },
873
+ children: message
874
+ }
875
+ );
876
+ }
877
+ function PayPalPaymentSection({
878
+ cartId,
879
+ selectedProviderId,
880
+ baseUrl,
881
+ publishableApiKey,
882
+ sessionLoading = false,
883
+ onSuccess,
884
+ onError,
885
+ onPaid
886
+ }) {
887
+ const shouldRender = isPayPalProviderId(selectedProviderId);
888
+ const { config, loading, error } = usePayPalConfig({
889
+ baseUrl,
890
+ publishableApiKey,
891
+ cartId,
892
+ enabled: shouldRender
893
+ });
894
+ const handlePaid = useCallback(
895
+ (captureResult) => {
896
+ onPaid?.(captureResult);
897
+ onSuccess?.(cartId);
898
+ },
899
+ [cartId, onPaid, onSuccess]
900
+ );
901
+ if (!shouldRender) return null;
902
+ if (sessionLoading) return /* @__PURE__ */ jsx(SessionInitCard, {});
903
+ if (loading) return /* @__PURE__ */ jsx(ConfigLoadingCard, {});
904
+ if (error) return /* @__PURE__ */ jsx(ErrorCard, { message: error });
905
+ if (!config) return null;
906
+ if (config.paypal_enabled === false && selectedProviderId === PAYPAL_WALLET_PROVIDER_ID) {
907
+ return null;
908
+ }
909
+ const isCardProvider = selectedProviderId === PAYPAL_CARD_PROVIDER_ID;
910
+ if (isCardProvider && config.card_enabled === false) return null;
911
+ const disableFunding = Array.isArray(config.disable_buttons) ? config.disable_buttons.join(",") : void 0;
912
+ return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 12 }, children: [
913
+ /* @__PURE__ */ jsx(PayPalCurrencyNotice, { config }),
914
+ /* @__PURE__ */ jsx(
915
+ PayPalProvider,
916
+ {
917
+ config,
918
+ intent: config.intent === "authorize" ? "authorize" : "capture",
919
+ disableFunding,
920
+ children: isCardProvider ? /* @__PURE__ */ jsx(
921
+ PayPalAdvancedCard,
922
+ {
923
+ baseUrl,
924
+ publishableApiKey,
925
+ cartId,
926
+ config,
927
+ onPaid: handlePaid,
928
+ onError
929
+ }
930
+ ) : /* @__PURE__ */ jsx(
931
+ PayPalSmartButtons,
932
+ {
933
+ baseUrl,
934
+ publishableApiKey,
935
+ cartId,
936
+ config,
937
+ onPaid: handlePaid,
938
+ onError
939
+ }
940
+ )
941
+ }
942
+ )
943
+ ] }, selectedProviderId);
944
+ }
945
+ var _cache2 = /* @__PURE__ */ new Map();
946
+ var CACHE_TTL2 = 5 * 60 * 1e3;
947
+ function cacheKey2(baseUrl, cartId) {
948
+ return `ppm::${baseUrl}::${cartId ?? ""}`;
949
+ }
950
+ var DEFAULT_RESULT = {
951
+ paypalEnabled: true,
952
+ paypalTitle: "PayPal",
953
+ cardEnabled: true,
954
+ cardTitle: "Credit or Debit Card",
955
+ loading: false
956
+ };
957
+ function usePayPalPaymentMethods({
958
+ baseUrl,
959
+ publishableApiKey,
960
+ cartId,
961
+ enabled = true
962
+ }) {
963
+ const api = useMemo(
964
+ () => createPayPalStoreApi({ baseUrl, publishableApiKey }),
965
+ [baseUrl, publishableApiKey]
966
+ );
967
+ const key = cacheKey2(baseUrl, cartId);
968
+ const hit = _cache2.get(key);
969
+ const seed = hit && Date.now() - hit.at < CACHE_TTL2 ? hit.result : null;
970
+ const [result, setResult] = useState(seed ?? { ...DEFAULT_RESULT, loading: enabled });
971
+ const fetchIdRef = useRef(0);
972
+ useEffect(() => {
973
+ if (!enabled) {
974
+ setResult((prev) => ({ ...prev, loading: false }));
975
+ return;
976
+ }
977
+ const k = cacheKey2(baseUrl, cartId);
978
+ const cached = _cache2.get(k);
979
+ if (cached && Date.now() - cached.at < CACHE_TTL2) {
980
+ setResult(cached.result);
981
+ return;
982
+ }
983
+ const id = ++fetchIdRef.current;
984
+ let mounted = true;
985
+ const controller = new AbortController();
986
+ setResult((prev) => ({ ...prev, loading: true }));
987
+ (async () => {
988
+ try {
989
+ const cfg = await api.getConfig(cartId, controller.signal);
990
+ if (!mounted || id !== fetchIdRef.current) return;
991
+ const next = {
992
+ paypalEnabled: cfg.paypal_enabled !== false,
993
+ paypalTitle: typeof cfg.paypal_title === "string" && cfg.paypal_title ? cfg.paypal_title : "PayPal",
994
+ cardEnabled: cfg.card_enabled !== false,
995
+ cardTitle: typeof cfg.card_title === "string" && cfg.card_title ? cfg.card_title : "Credit or Debit Card",
996
+ loading: false
997
+ };
998
+ _cache2.set(k, { result: next, at: Date.now() });
999
+ setResult(next);
1000
+ } catch (e) {
1001
+ if (e?.name === "AbortError") return;
1002
+ if (!mounted || id !== fetchIdRef.current) return;
1003
+ if (e?.message?.includes("403") || e?.message?.includes("Forbidden")) {
1004
+ const disabled = {
1005
+ ...DEFAULT_RESULT,
1006
+ paypalEnabled: false,
1007
+ cardEnabled: false,
1008
+ loading: false
1009
+ };
1010
+ setResult(disabled);
1011
+ return;
1012
+ }
1013
+ setResult({ ...DEFAULT_RESULT, loading: false });
1014
+ }
1015
+ })();
1016
+ return () => {
1017
+ mounted = false;
1018
+ controller.abort();
1019
+ };
1020
+ }, [api, baseUrl, cartId, enabled]);
1021
+ return result;
1022
+ }
778
1023
 
779
- export { MedusaNextPayPalAdapter, PayPalAdvancedCard, PayPalCurrencyNotice, PayPalProvider, PayPalSmartButtons, createPayPalStoreApi, usePayPalConfig };
1024
+ export { MedusaNextPayPalAdapter, PAYPAL_CARD_PROVIDER_ID, PAYPAL_WALLET_PROVIDER_ID, PayPalAdvancedCard, PayPalCurrencyNotice, PayPalPaymentSection, PayPalProvider, PayPalSmartButtons, createPayPalStoreApi, isPayPalProviderId, usePayPalConfig, usePayPalPaymentMethods };
780
1025
  //# sourceMappingURL=index.mjs.map