@easypayment/medusa-payment-paypal 0.9.21 → 0.9.22

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.
@@ -134,22 +134,20 @@ async function adminFetch(path, opts = {}) {
134
134
  }
135
135
  }
136
136
  const DEFAULT_FORM$1 = {
137
- enabled: true,
138
- title: "Credit or Debit Card",
139
- threeDS: "when_required"
137
+ paymentAction: "capture",
138
+ brandName: "PayPal",
139
+ landingPage: "no_preference",
140
+ requireInstantPayment: false,
141
+ sendItemDetails: true,
142
+ invoicePrefix: "PP-",
143
+ creditCardStatementName: "PayPal"
140
144
  };
141
145
  function mergeWithDefaults$1(saved) {
142
146
  if (!saved) return { ...DEFAULT_FORM$1 };
143
147
  const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
144
148
  return { ...DEFAULT_FORM$1, ...Object.fromEntries(entries) };
145
149
  }
146
- const THREE_DS_OPTIONS = [
147
- { value: "when_required", label: "3D Secure when required", hint: "Triggers 3DS only when the card / issuer requires it." },
148
- { value: "sli", label: "3D Secure (SCA) / liability shift (recommended)", hint: "Attempts to optimize for liability shift while remaining compliant." },
149
- { value: "always", label: "Always request 3D Secure", hint: "Forces 3DS challenge whenever possible (may reduce conversion)." }
150
- ];
151
- function AdvancedCardPaymentsTab() {
152
- var _a, _b;
150
+ function AdditionalSettingsTab() {
153
151
  const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM$1 }));
154
152
  const [loading, setLoading] = react.useState(false);
155
153
  const [saving, setSaving] = react.useState(false);
@@ -164,7 +162,7 @@ function AdvancedCardPaymentsTab() {
164
162
  setLoading(true);
165
163
  const json = await adminFetch("/admin/paypal/settings");
166
164
  const payload = (json == null ? void 0 : json.data) ?? json;
167
- const saved = payload == null ? void 0 : payload.advanced_card_payments;
165
+ const saved = payload == null ? void 0 : payload.additional_settings;
168
166
  if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
169
167
  } catch {
170
168
  } finally {
@@ -175,16 +173,14 @@ function AdvancedCardPaymentsTab() {
175
173
  async function onSave() {
176
174
  try {
177
175
  setSaving(true);
178
- const json = await adminFetch("/admin/paypal/settings", {
179
- method: "POST",
180
- body: { advanced_card_payments: form }
181
- });
176
+ setToast(null);
177
+ const json = await adminFetch("/admin/paypal/settings", { method: "POST", body: { additional_settings: form } });
182
178
  const payload = (json == null ? void 0 : json.data) ?? json;
183
- const saved = payload == null ? void 0 : payload.advanced_card_payments;
179
+ const saved = payload == null ? void 0 : payload.additional_settings;
184
180
  if (saved && typeof saved === "object") setForm(mergeWithDefaults$1(saved));
185
181
  setToast({ kind: "success", message: "Settings saved" });
186
182
  } catch (e) {
187
- setToast({ kind: "error", message: (e instanceof Error ? e.message : "") || "Failed to save settings." });
183
+ setToast({ kind: "error", message: e instanceof Error ? e.message : "Failed to save settings" });
188
184
  } finally {
189
185
  setSaving(false);
190
186
  }
@@ -196,42 +192,55 @@ function AdvancedCardPaymentsTab() {
196
192
  /* @__PURE__ */ jsxRuntime.jsx(
197
193
  SectionCard,
198
194
  {
199
- title: "Advanced Card Payments",
200
- description: "Control card checkout settings and 3D Secure behavior.",
195
+ title: "Additional Settings",
196
+ description: "These settings control checkout behavior and PayPal experience.",
201
197
  right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
202
198
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSave, disabled: saving || loading, className: "transition-fg relative inline-flex w-fit items-center justify-center overflow-hidden rounded-md outline-none shadow-buttons-neutral text-ui-fg-base bg-ui-button-neutral after:transition-fg after:absolute after:inset-0 after:content-[''] after:button-neutral-gradient hover:bg-ui-button-neutral-hover hover:after:button-neutral-hover-gradient active:bg-ui-button-neutral-pressed active:after:button-neutral-pressed-gradient focus-visible:shadow-buttons-neutral-focus disabled:bg-ui-bg-disabled disabled:border-ui-border-base disabled:text-ui-fg-disabled disabled:shadow-buttons-neutral disabled:after:hidden txt-compact-small-plus px-3 py-1.5", children: saving ? "Saving..." : "Save settings" }),
203
199
  loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
204
200
  ] }),
205
201
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
206
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Enable/Disable", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
207
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.enabled, onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
208
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
202
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Payment action", htmlFor: "as-payment-action", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { id: "as-payment-action", value: form.paymentAction, onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
203
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
204
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
209
205
  ] }) }),
210
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Title", htmlFor: "acp-title", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "acp-title", value: form.title, onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "Credit or Debit Card" }) }),
211
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Contingency for 3D Secure", hint: "Choose when 3D Secure should be triggered during card payments.", htmlFor: "acp-threeds", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
212
- /* @__PURE__ */ jsxRuntime.jsx("select", { id: "acp-threeds", value: form.threeDS, onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value)) }),
213
- ((_a = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _a.hint) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: (_b = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _b.hint }) : null
214
- ] }) })
206
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Brand Name", htmlFor: "as-brand-name", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-brand-name", value: form.brandName, onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) }),
207
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Landing Page", htmlFor: "as-landing-page", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { id: "as-landing-page", value: form.landingPage, onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
208
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
209
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
210
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
211
+ ] }) }),
212
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
213
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.requireInstantPayment, onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
214
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
215
+ ] }) }),
216
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Send Item Details", hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
217
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.sendItemDetails, onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
218
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
219
+ ] }) }),
220
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Invoice prefix", htmlFor: "as-invoice-prefix", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-invoice-prefix", value: form.invoicePrefix, onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PP-" }) }),
221
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Credit Card Statement Name", htmlFor: "as-cc-statement", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-cc-statement", value: form.creditCardStatementName, onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) })
215
222
  ] })
216
223
  }
217
224
  )
218
225
  ] }) });
219
226
  }
220
227
  const DEFAULT_FORM = {
221
- paymentAction: "capture",
222
- brandName: "PayPal",
223
- landingPage: "no_preference",
224
- requireInstantPayment: false,
225
- sendItemDetails: true,
226
- invoicePrefix: "PP-",
227
- creditCardStatementName: "PayPal"
228
+ enabled: true,
229
+ title: "Credit or Debit Card",
230
+ threeDS: "when_required"
228
231
  };
229
232
  function mergeWithDefaults(saved) {
230
233
  if (!saved) return { ...DEFAULT_FORM };
231
234
  const entries = Object.entries(saved).filter(([, value]) => value !== void 0);
232
235
  return { ...DEFAULT_FORM, ...Object.fromEntries(entries) };
233
236
  }
234
- function AdditionalSettingsTab() {
237
+ const THREE_DS_OPTIONS = [
238
+ { value: "when_required", label: "3D Secure when required", hint: "Triggers 3DS only when the card / issuer requires it." },
239
+ { value: "sli", label: "3D Secure (SCA) / liability shift (recommended)", hint: "Attempts to optimize for liability shift while remaining compliant." },
240
+ { value: "always", label: "Always request 3D Secure", hint: "Forces 3DS challenge whenever possible (may reduce conversion)." }
241
+ ];
242
+ function AdvancedCardPaymentsTab() {
243
+ var _a, _b;
235
244
  const [form, setForm] = react.useState(() => ({ ...DEFAULT_FORM }));
236
245
  const [loading, setLoading] = react.useState(false);
237
246
  const [saving, setSaving] = react.useState(false);
@@ -246,7 +255,7 @@ function AdditionalSettingsTab() {
246
255
  setLoading(true);
247
256
  const json = await adminFetch("/admin/paypal/settings");
248
257
  const payload = (json == null ? void 0 : json.data) ?? json;
249
- const saved = payload == null ? void 0 : payload.additional_settings;
258
+ const saved = payload == null ? void 0 : payload.advanced_card_payments;
250
259
  if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
251
260
  } catch {
252
261
  } finally {
@@ -257,14 +266,16 @@ function AdditionalSettingsTab() {
257
266
  async function onSave() {
258
267
  try {
259
268
  setSaving(true);
260
- setToast(null);
261
- const json = await adminFetch("/admin/paypal/settings", { method: "POST", body: { additional_settings: form } });
269
+ const json = await adminFetch("/admin/paypal/settings", {
270
+ method: "POST",
271
+ body: { advanced_card_payments: form }
272
+ });
262
273
  const payload = (json == null ? void 0 : json.data) ?? json;
263
- const saved = payload == null ? void 0 : payload.additional_settings;
274
+ const saved = payload == null ? void 0 : payload.advanced_card_payments;
264
275
  if (saved && typeof saved === "object") setForm(mergeWithDefaults(saved));
265
276
  setToast({ kind: "success", message: "Settings saved" });
266
277
  } catch (e) {
267
- setToast({ kind: "error", message: e instanceof Error ? e.message : "Failed to save settings" });
278
+ setToast({ kind: "error", message: (e instanceof Error ? e.message : "") || "Failed to save settings." });
268
279
  } finally {
269
280
  setSaving(false);
270
281
  }
@@ -276,33 +287,22 @@ function AdditionalSettingsTab() {
276
287
  /* @__PURE__ */ jsxRuntime.jsx(
277
288
  SectionCard,
278
289
  {
279
- title: "Additional Settings",
280
- description: "These settings control checkout behavior and PayPal experience.",
290
+ title: "Advanced Card Payments",
291
+ description: "Control card checkout settings and 3D Secure behavior.",
281
292
  right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
282
293
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSave, disabled: saving || loading, className: "transition-fg relative inline-flex w-fit items-center justify-center overflow-hidden rounded-md outline-none shadow-buttons-neutral text-ui-fg-base bg-ui-button-neutral after:transition-fg after:absolute after:inset-0 after:content-[''] after:button-neutral-gradient hover:bg-ui-button-neutral-hover hover:after:button-neutral-hover-gradient active:bg-ui-button-neutral-pressed active:after:button-neutral-pressed-gradient focus-visible:shadow-buttons-neutral-focus disabled:bg-ui-bg-disabled disabled:border-ui-border-base disabled:text-ui-fg-disabled disabled:shadow-buttons-neutral disabled:after:hidden txt-compact-small-plus px-3 py-1.5", children: saving ? "Saving..." : "Save settings" }),
283
294
  loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-subtle", children: "Loading…" }) : null
284
295
  ] }),
285
296
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-ui-border-base", children: [
286
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Payment action", htmlFor: "as-payment-action", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { id: "as-payment-action", value: form.paymentAction, onChange: (e) => setForm((p) => ({ ...p, paymentAction: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
287
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "capture", children: "Capture" }),
288
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "authorize", children: "Authorize" })
289
- ] }) }),
290
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Brand Name", htmlFor: "as-brand-name", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-brand-name", value: form.brandName, onChange: (e) => setForm((p) => ({ ...p, brandName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) }),
291
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Landing Page", htmlFor: "as-landing-page", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { id: "as-landing-page", value: form.landingPage, onChange: (e) => setForm((p) => ({ ...p, landingPage: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: [
292
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "no_preference", children: "No Preference" }),
293
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "login", children: "Login" }),
294
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "billing", children: "Billing" })
295
- ] }) }),
296
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Instant Payments", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
297
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.requireInstantPayment, onChange: (e) => setForm((p) => ({ ...p, requireInstantPayment: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
298
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Require Instant Payment" })
299
- ] }) }),
300
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Send Item Details", hint: "Include all line item details in the payment request to PayPal so that they can be seen from the PayPal transaction details page.", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
301
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.sendItemDetails, onChange: (e) => setForm((p) => ({ ...p, sendItemDetails: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
302
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Send line item details to PayPal" })
297
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Enable/Disable", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex items-center gap-2", children: [
298
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: form.enabled, onChange: (e) => setForm((p) => ({ ...p, enabled: e.target.checked })), className: "h-4 w-4 rounded border-ui-border-base" }),
299
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ui-fg-base", children: "Enable Advanced Credit/Debit Card" })
303
300
  ] }) }),
304
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Invoice prefix", htmlFor: "as-invoice-prefix", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-invoice-prefix", value: form.invoicePrefix, onChange: (e) => setForm((p) => ({ ...p, invoicePrefix: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PP-" }) }),
305
- /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Credit Card Statement Name", htmlFor: "as-cc-statement", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "as-cc-statement", value: form.creditCardStatementName, onChange: (e) => setForm((p) => ({ ...p, creditCardStatementName: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "PayPal" }) })
301
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Title", htmlFor: "acp-title", children: /* @__PURE__ */ jsxRuntime.jsx("input", { id: "acp-title", value: form.title, onChange: (e) => setForm((p) => ({ ...p, title: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", placeholder: "Credit or Debit Card" }) }),
302
+ /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { label: "Contingency for 3D Secure", hint: "Choose when 3D Secure should be triggered during card payments.", htmlFor: "acp-threeds", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
303
+ /* @__PURE__ */ jsxRuntime.jsx("select", { id: "acp-threeds", value: form.threeDS, onChange: (e) => setForm((p) => ({ ...p, threeDS: e.target.value })), className: "w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive", children: THREE_DS_OPTIONS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value)) }),
304
+ ((_a = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _a.hint) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-ui-fg-subtle", children: (_b = THREE_DS_OPTIONS.find((o) => o.value === form.threeDS)) == null ? void 0 : _b.hint }) : null
305
+ ] }) })
306
306
  ] })
307
307
  }
308
308
  )
@@ -324,7 +324,7 @@ const PARTNER_JS_URLS = {
324
324
  const SERVICE_URL = "/admin/paypal/onboarding-link";
325
325
  const POPUP_NAME = "PPFrame";
326
326
  const CACHE_PREFIX = "pp_onboard_cache";
327
- const CACHE_EXPIRY = 10 * 60 * 1e3;
327
+ const CACHE_EXPIRY = 6 * 60 * 60 * 1e3;
328
328
  const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete";
329
329
  const STATUS_ENDPOINT = "/admin/paypal/status";
330
330
  const SAVE_CREDENTIALS_ENDPOINT = "/admin/paypal/save-credentials";
@@ -347,7 +347,9 @@ function readCachedUrl(env) {
347
347
  function writeCachedUrl(env, url) {
348
348
  try {
349
349
  localStorage.setItem(cacheKeyFor(env), JSON.stringify({ url, ts: Date.now() }));
350
+ return readCachedUrl(env) === url;
350
351
  } catch {
352
+ return false;
351
353
  }
352
354
  }
353
355
  function clearCachedUrl(env) {
@@ -361,58 +363,12 @@ function clearCachedUrl(env) {
361
363
  } catch {
362
364
  }
363
365
  }
364
- function isPayPalOrigin(origin) {
365
- try {
366
- const host = new URL(origin).hostname.toLowerCase();
367
- return host === "www.paypal.com" || host === "www.sandbox.paypal.com" || host.endsWith(".paypal.com") || host.endsWith(".paypalobjects.com");
368
- } catch {
369
- return false;
370
- }
371
- }
372
- function extractAuth(data) {
373
- if (!data) return {};
374
- if (typeof data === "object") {
375
- const obj = data;
376
- const authCode = obj.authCode ?? obj.auth_code ?? obj.authcode;
377
- const sharedId = obj.sharedId ?? obj.shared_id ?? obj.sharedid;
378
- if (authCode && sharedId) {
379
- return { authCode: String(authCode), sharedId: String(sharedId) };
380
- }
381
- for (const key of ["data", "payload", "message", "detail", "body"]) {
382
- if (obj[key] && typeof obj[key] === "object") {
383
- const inner = extractAuth(obj[key]);
384
- if (inner.authCode && inner.sharedId) return inner;
385
- }
386
- }
387
- return {};
388
- }
389
- if (typeof data === "string") {
390
- const s = data.trim();
391
- if (!s) return {};
392
- if (s.startsWith("{")) {
393
- try {
394
- return extractAuth(JSON.parse(s));
395
- } catch {
396
- }
397
- }
398
- if (/auth_?code/i.test(s) && /shared_?id/i.test(s)) {
399
- try {
400
- const sp = new URLSearchParams(s.replace(/^[?#]/, ""));
401
- const authCode = sp.get("authCode") || sp.get("auth_code") || void 0;
402
- const sharedId = sp.get("sharedId") || sp.get("shared_id") || void 0;
403
- if (authCode && sharedId) return { authCode, sharedId };
404
- } catch {
405
- }
406
- }
407
- }
408
- return {};
409
- }
410
366
  function PayPalConnectionPage() {
411
367
  const [env, setEnv] = react.useState("live");
412
368
  const [envReady, setEnvReady] = react.useState(false);
413
369
  const [connState, setConnState] = react.useState("loading");
370
+ const [partnerReady, setPartnerReady] = react.useState(false);
414
371
  const [error, setError] = react.useState(null);
415
- const [popupBlocked, setPopupBlocked] = react.useState(false);
416
372
  const [finalUrl, setFinalUrl] = react.useState("");
417
373
  const [showManual, setShowManual] = react.useState(false);
418
374
  const [clientId, setClientId] = react.useState("");
@@ -420,20 +376,11 @@ function PayPalConnectionPage() {
420
376
  const [statusInfo, setStatusInfo] = react.useState(null);
421
377
  const [onboardingInProgress, setOnboardingInProgress] = react.useState(false);
422
378
  const initLoaderRef = react.useRef(null);
423
- const paypalButtonRef = react.useRef(null);
424
379
  const errorLogRef = react.useRef(null);
425
380
  const runIdRef = react.useRef(0);
426
381
  const currentRunId = react.useRef(0);
427
- const finalUrlRef = react.useRef(finalUrl);
428
- finalUrlRef.current = finalUrl;
429
- const connStateRef = react.useRef(connState);
430
- connStateRef.current = connState;
431
- const inProgressRef = react.useRef(onboardingInProgress);
432
- inProgressRef.current = onboardingInProgress;
433
382
  const envRef = react.useRef(env);
434
383
  envRef.current = env;
435
- const popupRef = react.useRef(null);
436
- const popupPollRef = react.useRef(null);
437
384
  const completedRef = react.useRef(false);
438
385
  const ppBtnMeasureRef = react.useRef(null);
439
386
  const [ppBtnWidth, setPpBtnWidth] = react.useState(null);
@@ -444,131 +391,23 @@ function PayPalConnectionPage() {
444
391
  setConnState("error");
445
392
  setError(msg);
446
393
  }, []);
447
- const stopPopupPoll = react.useCallback(() => {
448
- if (popupPollRef.current) {
449
- clearInterval(popupPollRef.current);
450
- popupPollRef.current = null;
451
- }
452
- }, []);
453
- const openOnboardingPopup = react.useCallback(
454
- (url) => {
455
- const w = 450;
456
- const h = 600;
457
- const baseLeft = typeof window.screenX === "number" ? window.screenX : window.screenLeft || 0;
458
- const baseTop = typeof window.screenY === "number" ? window.screenY : window.screenTop || 0;
459
- const outerW = window.outerWidth || document.documentElement.clientWidth || 1024;
460
- const outerH = window.outerHeight || document.documentElement.clientHeight || 768;
461
- const left = Math.round(baseLeft + Math.max(0, (outerW - w) / 2));
462
- const top = Math.round(baseTop + Math.max(0, (outerH - h) / 2));
463
- const features = `popup=yes,width=${w},height=${h},left=${left},top=${top},scrollbars=yes,resizable=yes`;
464
- let popup = null;
465
- try {
466
- popup = window.open(url, POPUP_NAME, features);
467
- } catch {
468
- popup = null;
469
- }
470
- if (popup) {
471
- popupRef.current = popup;
472
- try {
473
- popup.focus();
474
- } catch {
394
+ const generateLinkAndReload = react.useCallback(
395
+ async (targetEnv, runId) => {
396
+ if (initLoaderRef.current) {
397
+ const loaderText = initLoaderRef.current.querySelector("#loader-text");
398
+ if (loaderText) {
399
+ loaderText.textContent = "Generating onboarding session...";
475
400
  }
476
- stopPopupPoll();
477
- popupPollRef.current = setInterval(() => {
478
- if (!popupRef.current || popupRef.current.closed) {
479
- stopPopupPoll();
480
- }
481
- }, 1e3);
482
401
  }
483
- return popup;
484
- },
485
- [stopPopupPoll]
486
- );
487
- const completeOnboarding = react.useCallback(
488
- async (authCode, sharedId) => {
489
- var _a, _b, _c, _d, _e, _f, _g, _h;
490
- if (!authCode || !sharedId) return;
491
- if (completedRef.current) return;
492
- completedRef.current = true;
493
402
  try {
494
- window.onbeforeunload = null;
495
- } catch {
496
- }
497
- const activeEnv = envRef.current === "sandbox" ? "sandbox" : "live";
498
- setOnboardingInProgress(true);
499
- setConnState("loading");
500
- setError(null);
501
- setPopupBlocked(false);
502
- try {
503
- const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
403
+ const res = await fetch(SERVICE_URL, {
504
404
  method: "POST",
505
405
  headers: { "content-type": "application/json" },
506
406
  credentials: "include",
507
- body: JSON.stringify({ authCode, sharedId, env: activeEnv })
407
+ body: JSON.stringify({ products: ["PPCP"], environment: targetEnv })
508
408
  });
509
- if (!res.ok) {
510
- const txt = await res.text().catch(() => "");
511
- throw new Error(txt || `Onboarding exchange failed (${res.status})`);
512
- }
513
- try {
514
- (_a = popupRef.current) == null ? void 0 : _a.close();
515
- } catch {
516
- }
517
- stopPopupPoll();
518
- try {
519
- const close1 = (_e = (_d = (_c = (_b = window.PAYPAL) == null ? void 0 : _b.apps) == null ? void 0 : _c.Signup) == null ? void 0 : _d.MiniBrowser) == null ? void 0 : _e.closeFlow;
520
- if (typeof close1 === "function") close1();
521
- } catch {
522
- }
523
- try {
524
- const close2 = ((_h = (_g = (_f = window.PAYPAL) == null ? void 0 : _f.apps) == null ? void 0 : _g.Signup) == null ? void 0 : _h.miniBrowser) && window.PAYPAL.apps.Signup.miniBrowser.closeFlow;
525
- if (typeof close2 === "function") close2();
526
- } catch {
527
- }
528
- clearCachedUrl(activeEnv);
529
- try {
530
- const statusRes = await fetch(
531
- `${STATUS_ENDPOINT}?environment=${activeEnv}`,
532
- { method: "GET", credentials: "include" }
533
- );
534
- const refreshedStatus = await statusRes.json().catch(() => ({}));
535
- setStatusInfo(refreshedStatus || null);
536
- } catch {
537
- }
538
- setConnState("connected");
539
- setShowManual(false);
540
- } catch (e) {
541
- completedRef.current = false;
542
- console.error(e);
543
- setConnState("error");
544
- setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
545
- } finally {
546
- setOnboardingInProgress(false);
547
- }
548
- },
549
- [stopPopupPoll]
550
- );
551
- const fetchFreshLink = react.useCallback(
552
- (runId, targetEnv) => {
553
- if (initLoaderRef.current) {
554
- const loaderText = initLoaderRef.current.querySelector("#loader-text");
555
- if (loaderText)
556
- loaderText.textContent = "Generating onboarding session...";
557
- }
558
- fetch(SERVICE_URL, {
559
- method: "POST",
560
- headers: { "content-type": "application/json" },
561
- credentials: "include",
562
- body: JSON.stringify({
563
- products: ["PPCP"],
564
- // Generate the link for the explicitly selected environment so it can
565
- // never depend on a racing POST /environment having landed yet.
566
- environment: targetEnv
567
- })
568
- }).then((r) => {
569
- if (!r.ok) throw new Error(`Service returned ${r.status}`);
570
- return r.json();
571
- }).then((data) => {
409
+ if (!res.ok) throw new Error(`Service returned ${res.status}`);
410
+ const data = await res.json();
572
411
  if (runId !== currentRunId.current) return;
573
412
  const href = data == null ? void 0 : data.onboarding_url;
574
413
  if (!href) {
@@ -576,13 +415,17 @@ function PayPalConnectionPage() {
576
415
  return;
577
416
  }
578
417
  const url = href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser";
579
- writeCachedUrl(targetEnv, url);
418
+ const persisted = writeCachedUrl(targetEnv, url);
419
+ if (persisted) {
420
+ window.location.reload();
421
+ return;
422
+ }
580
423
  setFinalUrl(url);
581
424
  setConnState("ready");
582
- }).catch(() => {
425
+ } catch {
583
426
  if (runId !== currentRunId.current) return;
584
427
  showError("Unable to connect to service.");
585
- });
428
+ }
586
429
  },
587
430
  [showError]
588
431
  );
@@ -599,12 +442,60 @@ function PayPalConnectionPage() {
599
442
  alive = false;
600
443
  };
601
444
  }, []);
445
+ react.useEffect(() => {
446
+ if (!envReady) return;
447
+ currentRunId.current = ++runIdRef.current;
448
+ const runId = currentRunId.current;
449
+ let cancelled = false;
450
+ completedRef.current = false;
451
+ const run = async () => {
452
+ setConnState("loading");
453
+ setError(null);
454
+ setFinalUrl("");
455
+ try {
456
+ const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
457
+ method: "GET",
458
+ credentials: "include"
459
+ });
460
+ const st = await r.json().catch(() => ({}));
461
+ if (cancelled || runId !== currentRunId.current) return;
462
+ setStatusInfo(st);
463
+ const isConnected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
464
+ if (isConnected) {
465
+ setConnState("connected");
466
+ setShowManual(false);
467
+ return;
468
+ }
469
+ } catch (e) {
470
+ console.error(e);
471
+ }
472
+ if (cancelled || runId !== currentRunId.current) return;
473
+ const cached = readCachedUrl(env);
474
+ if (cached) {
475
+ setFinalUrl(cached);
476
+ setConnState("ready");
477
+ return;
478
+ }
479
+ await generateLinkAndReload(env, runId);
480
+ };
481
+ run();
482
+ return () => {
483
+ cancelled = true;
484
+ };
485
+ }, [env, envReady, generateLinkAndReload]);
602
486
  react.useEffect(() => {
603
487
  var _a, _b, _c;
604
488
  if (connState !== "ready" || !finalUrl) return;
605
489
  const scriptUrl = PARTNER_JS_URLS[env];
606
490
  let cancelled = false;
607
491
  let pollTimer;
492
+ setPartnerReady(false);
493
+ const readyFallback = setTimeout(() => {
494
+ if (!cancelled) setPartnerReady(true);
495
+ }, 6e3);
496
+ const markReady = () => {
497
+ if (!cancelled) setPartnerReady(true);
498
+ };
608
499
  const initPartner = (attempt = 0) => {
609
500
  var _a2, _b2;
610
501
  if (cancelled) return;
@@ -616,6 +507,7 @@ function PayPalConnectionPage() {
616
507
  } catch (e) {
617
508
  console.error("[paypal] partner.js init failed:", e);
618
509
  }
510
+ markReady();
619
511
  return;
620
512
  }
621
513
  if (typeof (signup == null ? void 0 : signup.render) === "function") {
@@ -624,6 +516,7 @@ function PayPalConnectionPage() {
624
516
  } catch (e) {
625
517
  console.error("[paypal] partner.js render failed:", e);
626
518
  }
519
+ markReady();
627
520
  return;
628
521
  }
629
522
  if (attempt < 40) {
@@ -634,6 +527,7 @@ function PayPalConnectionPage() {
634
527
  document.dispatchEvent(new Event("DOMContentLoaded"));
635
528
  } catch {
636
529
  }
530
+ markReady();
637
531
  };
638
532
  const existingScript = document.getElementById("paypal-partner-js");
639
533
  if (existingScript) {
@@ -650,9 +544,11 @@ function PayPalConnectionPage() {
650
544
  ppScript.src = scriptUrl;
651
545
  ppScript.async = true;
652
546
  ppScript.onload = () => initPartner();
547
+ ppScript.onerror = () => markReady();
653
548
  document.body.appendChild(ppScript);
654
549
  return () => {
655
550
  cancelled = true;
551
+ clearTimeout(readyFallback);
656
552
  if (pollTimer) {
657
553
  clearTimeout(pollTimer);
658
554
  }
@@ -661,59 +557,61 @@ function PayPalConnectionPage() {
661
557
  }
662
558
  };
663
559
  }, [connState, finalUrl, env]);
664
- react.useEffect(() => {
665
- const onMessage = (ev) => {
666
- if (!isPayPalOrigin(ev.origin)) return;
667
- const { authCode, sharedId } = extractAuth(ev.data);
668
- if (authCode && sharedId) {
669
- completeOnboarding(authCode, sharedId);
560
+ const completeOnboarding = react.useCallback(async (authCode, sharedId) => {
561
+ var _a, _b, _c, _d, _e, _f, _g;
562
+ if (!authCode || !sharedId) return;
563
+ if (completedRef.current) return;
564
+ completedRef.current = true;
565
+ try {
566
+ window.onbeforeunload = null;
567
+ } catch {
568
+ }
569
+ const activeEnv = envRef.current === "sandbox" ? "sandbox" : "live";
570
+ setOnboardingInProgress(true);
571
+ setConnState("loading");
572
+ setError(null);
573
+ try {
574
+ const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
575
+ method: "POST",
576
+ headers: { "content-type": "application/json" },
577
+ credentials: "include",
578
+ body: JSON.stringify({ authCode, sharedId, env: activeEnv })
579
+ });
580
+ if (!res.ok) {
581
+ const txt = await res.text().catch(() => "");
582
+ throw new Error(txt || `Onboarding exchange failed (${res.status})`);
670
583
  }
671
- };
672
- window.addEventListener("message", onMessage);
673
- return () => window.removeEventListener("message", onMessage);
674
- }, [completeOnboarding]);
675
- react.useEffect(() => {
676
- if (!envReady) return;
677
- currentRunId.current = ++runIdRef.current;
678
- const runId = currentRunId.current;
679
- let cancelled = false;
680
- completedRef.current = false;
681
- const run = async () => {
682
- setConnState("loading");
683
- setError(null);
684
- setPopupBlocked(false);
685
- setFinalUrl("");
686
584
  try {
687
- const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
585
+ const close1 = (_d = (_c = (_b = (_a = window.PAYPAL) == null ? void 0 : _a.apps) == null ? void 0 : _b.Signup) == null ? void 0 : _c.MiniBrowser) == null ? void 0 : _d.closeFlow;
586
+ if (typeof close1 === "function") close1();
587
+ } catch {
588
+ }
589
+ try {
590
+ const close2 = ((_g = (_f = (_e = window.PAYPAL) == null ? void 0 : _e.apps) == null ? void 0 : _f.Signup) == null ? void 0 : _g.miniBrowser) && window.PAYPAL.apps.Signup.miniBrowser.closeFlow;
591
+ if (typeof close2 === "function") close2();
592
+ } catch {
593
+ }
594
+ clearCachedUrl(activeEnv);
595
+ try {
596
+ const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${activeEnv}`, {
688
597
  method: "GET",
689
598
  credentials: "include"
690
599
  });
691
- const st = await r.json().catch(() => ({}));
692
- if (cancelled || runId !== currentRunId.current) return;
693
- setStatusInfo(st);
694
- const isConnected = (st == null ? void 0 : st.status) === "connected" && (st == null ? void 0 : st.seller_client_id_present) === true;
695
- if (isConnected) {
696
- setConnState("connected");
697
- setShowManual(false);
698
- return;
699
- }
700
- } catch (e) {
701
- console.error(e);
702
- }
703
- if (cancelled || runId !== currentRunId.current) return;
704
- const cached = readCachedUrl(env);
705
- if (cached) {
706
- setFinalUrl(cached);
707
- setConnState("ready");
708
- } else {
709
- fetchFreshLink(runId, env);
600
+ const refreshedStatus = await statusRes.json().catch(() => ({}));
601
+ setStatusInfo(refreshedStatus || null);
602
+ } catch {
710
603
  }
711
- };
712
- run();
713
- return () => {
714
- cancelled = true;
715
- };
716
- }, [env, envReady, fetchFreshLink]);
604
+ setConnState("connected");
605
+ setShowManual(false);
606
+ } catch (e) {
607
+ completedRef.current = false;
608
+ console.error(e);
609
+ setConnState("error");
610
+ setError((e == null ? void 0 : e.message) || "Exchange failed while saving credentials.");
611
+ } finally {
612
+ setOnboardingInProgress(false);
613
+ }
614
+ }, []);
717
615
  react.useLayoutEffect(() => {
718
616
  window.onboardingCallback = (authCode, sharedId) => {
719
617
  completeOnboarding(authCode, sharedId);
@@ -722,11 +620,6 @@ function PayPalConnectionPage() {
722
620
  window.onboardingCallback = void 0;
723
621
  };
724
622
  }, [completeOnboarding]);
725
- react.useEffect(() => {
726
- return () => {
727
- stopPopupPoll();
728
- };
729
- }, [stopPopupPoll]);
730
623
  react.useLayoutEffect(() => {
731
624
  const el = ppBtnMeasureRef.current;
732
625
  if (!el) return;
@@ -747,26 +640,6 @@ function PayPalConnectionPage() {
747
640
  else window.removeEventListener("resize", update);
748
641
  };
749
642
  }, [connState, env, finalUrl]);
750
- react.useEffect(() => {
751
- const onCaptureClick = (e) => {
752
- const btn = paypalButtonRef.current;
753
- if (!btn) return;
754
- const target = e.target;
755
- if (!target || !btn.contains(target)) return;
756
- e.preventDefault();
757
- if (connStateRef.current !== "ready" || !finalUrlRef.current || inProgressRef.current) {
758
- return;
759
- }
760
- completedRef.current = false;
761
- const popup = openOnboardingPopup(finalUrlRef.current);
762
- setPopupBlocked(!popup);
763
- };
764
- document.addEventListener("click", onCaptureClick, true);
765
- return () => document.removeEventListener("click", onCaptureClick, true);
766
- }, [openOnboardingPopup]);
767
- const handleConnectClick = (e) => {
768
- e.preventDefault();
769
- };
770
643
  const handleSaveManual = async () => {
771
644
  if (!canSaveManual || onboardingInProgress) return;
772
645
  setOnboardingInProgress(true);
@@ -827,8 +700,7 @@ function PayPalConnectionPage() {
827
700
  clearCachedUrl(env);
828
701
  completedRef.current = false;
829
702
  currentRunId.current = ++runIdRef.current;
830
- const runId = currentRunId.current;
831
- fetchFreshLink(runId, env);
703
+ await generateLinkAndReload(env, currentRunId.current);
832
704
  } catch (e) {
833
705
  console.error(e);
834
706
  setConnState("error");
@@ -839,10 +711,10 @@ function PayPalConnectionPage() {
839
711
  };
840
712
  const handleEnvChange = async (e) => {
841
713
  const next = e.target.value;
714
+ if (next === env || onboardingInProgress) return;
842
715
  completedRef.current = false;
843
- setPopupBlocked(false);
844
716
  clearCachedUrl();
845
- setEnv(next);
717
+ setConnState("loading");
846
718
  try {
847
719
  await fetch(ENVIRONMENT_ENDPOINT, {
848
720
  method: "POST",
@@ -852,6 +724,7 @@ function PayPalConnectionPage() {
852
724
  });
853
725
  } catch {
854
726
  }
727
+ setEnv(next);
855
728
  };
856
729
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6", children: [
857
730
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
@@ -911,7 +784,6 @@ function PayPalConnectionPage() {
911
784
  "a",
912
785
  {
913
786
  ref: (node) => {
914
- paypalButtonRef.current = node;
915
787
  ppBtnMeasureRef.current = node;
916
788
  },
917
789
  id: "paypal-button",
@@ -919,17 +791,19 @@ function PayPalConnectionPage() {
919
791
  "data-paypal-button": "true",
920
792
  href: finalUrl || "#",
921
793
  "data-paypal-onboard-complete": "onboardingCallback",
922
- onClick: handleConnectClick,
794
+ "aria-disabled": onboardingInProgress || !partnerReady,
923
795
  className: "transition-fg relative inline-flex w-fit items-center justify-center overflow-hidden rounded-md outline-none no-underline shadow-buttons-neutral text-ui-fg-base bg-ui-button-neutral after:transition-fg after:absolute after:inset-0 after:content-[''] after:button-neutral-gradient hover:bg-ui-button-neutral-hover hover:after:button-neutral-hover-gradient active:bg-ui-button-neutral-pressed active:after:button-neutral-pressed-gradient focus-visible:shadow-buttons-neutral-focus disabled:bg-ui-bg-disabled disabled:border-ui-border-base disabled:text-ui-fg-disabled disabled:shadow-buttons-neutral disabled:after:hidden txt-compact-small-plus px-3 py-1.5",
924
796
  style: {
925
- cursor: onboardingInProgress ? "not-allowed" : "pointer",
926
- opacity: onboardingInProgress ? 0.6 : 1,
927
- pointerEvents: onboardingInProgress ? "none" : "auto"
797
+ cursor: onboardingInProgress || !partnerReady ? "not-allowed" : "pointer",
798
+ opacity: onboardingInProgress || !partnerReady ? 0.6 : 1,
799
+ // Keep the anchor mounted (partner.js must find it to bind)
800
+ // but un-clickable until partner.js has taken over the
801
+ // click — so it can never open a tab via the native href.
802
+ pointerEvents: onboardingInProgress || !partnerReady ? "none" : "auto"
928
803
  },
929
- children: "Connect to PayPal"
804
+ children: partnerReady || onboardingInProgress ? "Connect to PayPal" : "Preparing PayPal…"
930
805
  }
931
806
  ),
932
- popupBlocked && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 text-left text-xs bg-amber-50 text-amber-700 p-3 border border-amber-200 rounded", children: "Your browser blocked the PayPal popup. Please allow popups for this site, then click “Connect to PayPal” again." }),
933
807
  /* @__PURE__ */ jsxRuntime.jsx(
934
808
  "div",
935
809
  {
@@ -1302,14 +1176,14 @@ const routeModule = {
1302
1176
  Component: PayPalSettingsIndexRoute,
1303
1177
  path: "/settings/paypal"
1304
1178
  },
1305
- {
1306
- Component: AdvancedCardPaymentsTab,
1307
- path: "/settings/paypal/advanced-card-payments"
1308
- },
1309
1179
  {
1310
1180
  Component: AdditionalSettingsTab,
1311
1181
  path: "/settings/paypal/additional-settings"
1312
1182
  },
1183
+ {
1184
+ Component: AdvancedCardPaymentsTab,
1185
+ path: "/settings/paypal/advanced-card-payments"
1186
+ },
1313
1187
  {
1314
1188
  Component: PayPalApplePayPage,
1315
1189
  path: "/settings/paypal/apple-pay"