@aforoai/storefront-widgets 1.0.5 → 1.0.11

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.
@@ -5,7 +5,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  // src/vanilla/index.ts
6
6
 
7
7
  // src/core/version.ts
8
- var VERSION = "1.0.5";
8
+ var VERSION = "1.0.11";
9
9
 
10
10
  // src/core/AforoEmbed.ts
11
11
  var mountedElements = /* @__PURE__ */ new WeakMap();
@@ -160,6 +160,7 @@ function pricingCardConfigToProps(config) {
160
160
  const theme = readEnum(extra.theme, ["light", "dark", "auto"], "auto");
161
161
  const locale = typeof extra.locale === "string" ? extra.locale : void 0;
162
162
  const maxPlans = typeof extra.maxPlans === "number" && Number.isFinite(extra.maxPlans) ? extra.maxPlans : void 0;
163
+ const borderRadius = typeof extra.borderRadius === "number" && Number.isFinite(extra.borderRadius) ? extra.borderRadius : void 0;
163
164
  const ctaText = typeof extra.ctaText === "string" ? extra.ctaText : void 0;
164
165
  const ctaUrl = typeof extra.ctaUrl === "string" ? extra.ctaUrl : void 0;
165
166
  const showFeatures = typeof extra.showFeatures === "boolean" ? extra.showFeatures : void 0;
@@ -173,6 +174,7 @@ function pricingCardConfigToProps(config) {
173
174
  theme,
174
175
  locale,
175
176
  maxPlans,
177
+ borderRadius,
176
178
  showFeatures,
177
179
  ctaText,
178
180
  ctaUrl,
@@ -864,8 +866,9 @@ var _BridgeClient = class _BridgeClient {
864
866
  }
865
867
  if (!resp.ok) return emptyPage;
866
868
  try {
867
- const body = await resp.json();
868
- if (!body || typeof body !== "object") return emptyPage;
869
+ const raw = await resp.json();
870
+ if (!raw || typeof raw !== "object") return emptyPage;
871
+ const body = raw.data ?? raw;
869
872
  return {
870
873
  content: Array.isArray(body.content) ? body.content : [],
871
874
  totalElements: typeof body.totalElements === "number" && Number.isFinite(body.totalElements) ? body.totalElements : 0,
@@ -908,7 +911,8 @@ var _BridgeClient = class _BridgeClient {
908
911
  }
909
912
  if (!resp.ok) return null;
910
913
  try {
911
- const body = await resp.json();
914
+ const raw = await resp.json();
915
+ const body = raw ? raw.data ?? raw : null;
912
916
  if (!body || typeof body.downloadUrl !== "string" || body.downloadUrl.length === 0) {
913
917
  return null;
914
918
  }
@@ -997,7 +1001,8 @@ var _BridgeClient = class _BridgeClient {
997
1001
  }
998
1002
  let body;
999
1003
  try {
1000
- body = await resp.json();
1004
+ const raw = await resp.json();
1005
+ body = raw?.data ?? raw;
1001
1006
  } catch {
1002
1007
  throw new BridgeClientError(
1003
1008
  "Malformed invoice-payment-initiate response (not JSON)",
@@ -1308,9 +1313,9 @@ var _BridgeClient = class _BridgeClient {
1308
1313
  if (!resp.ok) {
1309
1314
  throw await this.parseError(resp);
1310
1315
  }
1311
- let body;
1316
+ let raw;
1312
1317
  try {
1313
- body = await resp.json();
1318
+ raw = await resp.json();
1314
1319
  } catch {
1315
1320
  throw new BridgeClientError(
1316
1321
  "Malformed confirmCart response (not JSON)",
@@ -1319,6 +1324,7 @@ var _BridgeClient = class _BridgeClient {
1319
1324
  false
1320
1325
  );
1321
1326
  }
1327
+ const body = raw?.data ?? raw ?? {};
1322
1328
  if (!body.cartId || !body.status) {
1323
1329
  throw new BridgeClientError(
1324
1330
  "Malformed confirmCart response (missing required fields)",
@@ -1383,9 +1389,9 @@ var _BridgeClient = class _BridgeClient {
1383
1389
  * undefined access.
1384
1390
  */
1385
1391
  async parseCartResponse(resp, methodName) {
1386
- let body;
1392
+ let raw;
1387
1393
  try {
1388
- body = await resp.json();
1394
+ raw = await resp.json();
1389
1395
  } catch {
1390
1396
  throw new BridgeClientError(
1391
1397
  `Malformed ${methodName} response (not JSON)`,
@@ -1394,7 +1400,8 @@ var _BridgeClient = class _BridgeClient {
1394
1400
  false
1395
1401
  );
1396
1402
  }
1397
- if (!body.cartId || !body.cartType || !body.status || !body.targetId) {
1403
+ const data = raw?.data ?? raw ?? {};
1404
+ if (!data.cartId || !data.cartType || !data.status || !data.targetId) {
1398
1405
  throw new BridgeClientError(
1399
1406
  `Malformed ${methodName} response (missing required fields)`,
1400
1407
  500,
@@ -1403,21 +1410,21 @@ var _BridgeClient = class _BridgeClient {
1403
1410
  );
1404
1411
  }
1405
1412
  return {
1406
- cartId: body.cartId,
1407
- cartType: body.cartType,
1408
- targetId: body.targetId,
1409
- status: body.status,
1410
- totalCents: typeof body.totalCents === "number" && Number.isFinite(body.totalCents) ? body.totalCents : 0,
1411
- currency: typeof body.currency === "string" ? body.currency : "USD",
1412
- gatewayProvider: body.gatewayProvider ?? null,
1413
- gatewayClientSecret: body.gatewayClientSecret ?? null,
1414
- gatewayOrderId: body.gatewayOrderId ?? null,
1415
- gatewayApprovalUrl: body.gatewayApprovalUrl ?? null,
1416
- gatewaySandboxMode: body.gatewaySandboxMode ?? null,
1417
- subscriptionId: body.subscriptionId ?? null,
1418
- invoiceId: body.invoiceId ?? null,
1419
- expiresAt: typeof body.expiresAt === "string" ? body.expiresAt : (/* @__PURE__ */ new Date(0)).toISOString(),
1420
- completedAt: body.completedAt ?? null
1413
+ cartId: data.cartId,
1414
+ cartType: data.cartType,
1415
+ targetId: data.targetId,
1416
+ status: data.status,
1417
+ totalCents: typeof data.totalCents === "number" && Number.isFinite(data.totalCents) ? data.totalCents : 0,
1418
+ currency: typeof data.currency === "string" ? data.currency : "USD",
1419
+ gatewayProvider: data.gatewayProvider ?? null,
1420
+ gatewayClientSecret: data.gatewayClientSecret ?? null,
1421
+ gatewayOrderId: data.gatewayOrderId ?? null,
1422
+ gatewayApprovalUrl: data.gatewayApprovalUrl ?? null,
1423
+ gatewaySandboxMode: data.gatewaySandboxMode ?? null,
1424
+ subscriptionId: data.subscriptionId ?? null,
1425
+ invoiceId: data.invoiceId ?? null,
1426
+ expiresAt: typeof data.expiresAt === "string" ? data.expiresAt : (/* @__PURE__ */ new Date(0)).toISOString(),
1427
+ completedAt: data.completedAt ?? null
1421
1428
  };
1422
1429
  }
1423
1430
  /** Public liveness probe. Returns null on failure (not an error). */
@@ -1778,14 +1785,17 @@ var _BridgeClient = class _BridgeClient {
1778
1785
  idempotencyKey,
1779
1786
  sessionJwt
1780
1787
  }),
1781
- body: JSON.stringify(request)
1788
+ // 2026-08-29 fix: same bug as cancelSubscription() below — EmbedUpgradeRequest
1789
+ // requires idempotencyKey as a @NotBlank BODY field, but this only ever sent
1790
+ // it via the Idempotency-Key header.
1791
+ body: JSON.stringify({ ...request, idempotencyKey })
1782
1792
  });
1783
1793
  if (!resp.ok) {
1784
1794
  throw await this.parseError(resp);
1785
1795
  }
1786
- let body;
1796
+ let raw;
1787
1797
  try {
1788
- body = await resp.json();
1798
+ raw = await resp.json();
1789
1799
  } catch {
1790
1800
  throw new BridgeClientError(
1791
1801
  "Malformed upgrade response (not JSON)",
@@ -1794,6 +1804,7 @@ var _BridgeClient = class _BridgeClient {
1794
1804
  false
1795
1805
  );
1796
1806
  }
1807
+ const body = raw ? raw.data ?? raw : {};
1797
1808
  if (!body.subscriptionId || !body.previousOfferingId || !body.newOfferingId || !body.status) {
1798
1809
  throw new BridgeClientError(
1799
1810
  "Malformed upgrade response (missing required fields)",
@@ -1857,14 +1868,19 @@ var _BridgeClient = class _BridgeClient {
1857
1868
  idempotencyKey,
1858
1869
  sessionJwt
1859
1870
  }),
1860
- body: JSON.stringify(request)
1871
+ // 2026-08-29 fix: EmbedCancelRequest (storefront-service) requires
1872
+ // idempotencyKey as a @NotBlank BODY field — this only ever sent it
1873
+ // via the Idempotency-Key header, so every real cancellation 400'd
1874
+ // with "idempotencyKey is required" regardless of any other field.
1875
+ // Confirmed live against production.
1876
+ body: JSON.stringify({ ...request, idempotencyKey })
1861
1877
  });
1862
1878
  if (!resp.ok) {
1863
1879
  throw await this.parseError(resp);
1864
1880
  }
1865
- let body;
1881
+ let raw;
1866
1882
  try {
1867
- body = await resp.json();
1883
+ raw = await resp.json();
1868
1884
  } catch {
1869
1885
  throw new BridgeClientError(
1870
1886
  "Malformed cancel response (not JSON)",
@@ -1873,7 +1889,8 @@ var _BridgeClient = class _BridgeClient {
1873
1889
  false
1874
1890
  );
1875
1891
  }
1876
- if (!body.subscriptionId || !body.status || !body.effectiveAt || !body.feedbackId) {
1892
+ const body = raw ? raw.data ?? raw : null;
1893
+ if (!body || !body.subscriptionId || !body.status || !body.effectiveAt) {
1877
1894
  throw new BridgeClientError(
1878
1895
  "Malformed cancel response (missing required fields)",
1879
1896
  500,
@@ -1886,7 +1903,7 @@ var _BridgeClient = class _BridgeClient {
1886
1903
  status: body.status,
1887
1904
  cancelledAt: body.cancelledAt ?? null,
1888
1905
  effectiveAt: body.effectiveAt,
1889
- feedbackId: body.feedbackId,
1906
+ feedbackId: body.feedbackId ?? null,
1890
1907
  creditNoteId: body.creditNoteId ?? null
1891
1908
  };
1892
1909
  }
@@ -1916,7 +1933,8 @@ var _BridgeClient = class _BridgeClient {
1916
1933
  if (!resp.ok) {
1917
1934
  return { methods: [], defaultMethodId: null };
1918
1935
  }
1919
- const body = await resp.json();
1936
+ const raw = await resp.json();
1937
+ const body = raw ? raw.data ?? raw : {};
1920
1938
  return {
1921
1939
  methods: Array.isArray(body.methods) ? body.methods : [],
1922
1940
  defaultMethodId: body.defaultMethodId ?? null
@@ -1946,7 +1964,8 @@ var _BridgeClient = class _BridgeClient {
1946
1964
  body: JSON.stringify({})
1947
1965
  });
1948
1966
  if (!resp.ok) return null;
1949
- const body = await resp.json();
1967
+ const raw = await resp.json();
1968
+ const body = raw ? raw.data ?? raw : {};
1950
1969
  if (!body.clientSecret) return null;
1951
1970
  return {
1952
1971
  clientSecret: body.clientSecret,
@@ -3026,6 +3045,7 @@ function WidgetShell(props) {
3026
3045
  var DEFAULT_LAYOUT = "horizontal";
3027
3046
  var DEFAULT_MAX_PLANS = 4;
3028
3047
  var DEFAULT_CTA_TEXT = "Get Started";
3048
+ var DEFAULT_CARD_RADIUS = 12;
3029
3049
  function clampLayout(raw) {
3030
3050
  return raw === "horizontal" || raw === "vertical" || raw === "table" ? raw : void 0;
3031
3051
  }
@@ -3036,7 +3056,7 @@ function setTenantDefaultsIdempotent(setter, next) {
3036
3056
  setter((prev) => {
3037
3057
  if (prev === next) return prev;
3038
3058
  if (!prev && !next) return prev;
3039
- if (prev && next && prev.layout === next.layout && prev.theme === next.theme && prev.maxPlans === next.maxPlans && prev.showFeatures === next.showFeatures && prev.ctaText === next.ctaText) {
3059
+ if (prev && next && prev.layout === next.layout && prev.theme === next.theme && prev.maxPlans === next.maxPlans && prev.showFeatures === next.showFeatures && prev.ctaText === next.ctaText && prev.borderRadius === next.borderRadius) {
3040
3060
  return prev;
3041
3061
  }
3042
3062
  return next;
@@ -3051,7 +3071,8 @@ function extractTenantDefaults(config) {
3051
3071
  theme: typeof raw.theme === "string" ? raw.theme : void 0,
3052
3072
  maxPlans: typeof raw.maxPlans === "number" && Number.isFinite(raw.maxPlans) ? raw.maxPlans : void 0,
3053
3073
  showFeatures: typeof raw.showFeatures === "boolean" ? raw.showFeatures : void 0,
3054
- ctaText: typeof raw.ctaText === "string" && raw.ctaText.length > 0 ? raw.ctaText : void 0
3074
+ ctaText: typeof raw.ctaText === "string" && raw.ctaText.length > 0 ? raw.ctaText : void 0,
3075
+ borderRadius: typeof raw.borderRadius === "number" && Number.isFinite(raw.borderRadius) ? raw.borderRadius : void 0
3055
3076
  };
3056
3077
  }
3057
3078
  var DARK_TOKEN_OVERLAY = {
@@ -3173,6 +3194,7 @@ function PricingCardBody(props) {
3173
3194
  theme: themeProp,
3174
3195
  locale: localeProp,
3175
3196
  maxPlans: maxPlansProp,
3197
+ borderRadius: borderRadiusProp,
3176
3198
  showFeatures: showFeaturesProp,
3177
3199
  ctaText: ctaTextProp,
3178
3200
  ctaUrl: ctaUrlProp,
@@ -3186,6 +3208,7 @@ function PricingCardBody(props) {
3186
3208
  const maxPlans = typeof maxPlansProp === "number" && Number.isFinite(maxPlansProp) ? maxPlansProp : typeof tenantDefaults?.maxPlans === "number" && Number.isFinite(tenantDefaults.maxPlans) ? tenantDefaults.maxPlans : DEFAULT_MAX_PLANS;
3187
3209
  const showFeatures = typeof showFeaturesProp === "boolean" ? showFeaturesProp : typeof tenantDefaults?.showFeatures === "boolean" ? tenantDefaults.showFeatures : true;
3188
3210
  const ctaTextEffective = ctaTextProp ?? tenantDefaults?.ctaText ?? void 0;
3211
+ const cardRadius = typeof borderRadiusProp === "number" && Number.isFinite(borderRadiusProp) ? borderRadiusProp : typeof tenantDefaults?.borderRadius === "number" && Number.isFinite(tenantDefaults.borderRadius) ? tenantDefaults.borderRadius : DEFAULT_CARD_RADIUS;
3189
3212
  const shell = useWidgetShell();
3190
3213
  const { tokens: shellTokens, bridgeClient, telemetry, bus, tenantSlug } = shell;
3191
3214
  const isDark = React7.useMemo(() => {
@@ -3403,7 +3426,8 @@ function PricingCardBody(props) {
3403
3426
  {
3404
3427
  layout,
3405
3428
  tokens,
3406
- prefersReducedMotion
3429
+ prefersReducedMotion,
3430
+ cardRadius
3407
3431
  }
3408
3432
  )
3409
3433
  }
@@ -3475,7 +3499,8 @@ function PricingCardBody(props) {
3475
3499
  ctaTextProp: ctaTextEffective,
3476
3500
  featuredOverride: featuredOfferingId,
3477
3501
  onCtaClick: handleCtaClick,
3478
- intlOverride
3502
+ intlOverride,
3503
+ cardRadius
3479
3504
  }
3480
3505
  )
3481
3506
  }
@@ -3490,7 +3515,8 @@ function PlanGrid({
3490
3515
  ctaTextProp,
3491
3516
  featuredOverride,
3492
3517
  onCtaClick,
3493
- intlOverride
3518
+ intlOverride,
3519
+ cardRadius
3494
3520
  }) {
3495
3521
  const isHorizontal = layout === "horizontal";
3496
3522
  const gridStyle2 = isHorizontal ? {
@@ -3513,7 +3539,8 @@ function PlanGrid({
3513
3539
  ctaTextProp,
3514
3540
  featured: offeringIsFeatured(o, featuredOverride),
3515
3541
  onCtaClick,
3516
- intlOverride
3542
+ intlOverride,
3543
+ cardRadius
3517
3544
  },
3518
3545
  o.offeringId
3519
3546
  )) });
@@ -3526,7 +3553,8 @@ function PlanCard({
3526
3553
  ctaTextProp,
3527
3554
  featured,
3528
3555
  onCtaClick,
3529
- intlOverride
3556
+ intlOverride,
3557
+ cardRadius
3530
3558
  }) {
3531
3559
  const { text: price, unitSuffix } = resolveDisplayPrice(offering, locale, intlOverride);
3532
3560
  const isContactSales = price === "\u2014";
@@ -3537,7 +3565,7 @@ function PlanCard({
3537
3565
  display: "flex",
3538
3566
  flexDirection: "column",
3539
3567
  padding: 24,
3540
- borderRadius: 12,
3568
+ borderRadius: cardRadius,
3541
3569
  border: featured ? `2px solid ${tokens.primary}` : `1px solid ${tokens.border}`,
3542
3570
  background: tokens.bg,
3543
3571
  color: tokens.text,
@@ -3887,7 +3915,8 @@ function cellAria(label, feature) {
3887
3915
  function LoadingSkeleton({
3888
3916
  layout,
3889
3917
  tokens,
3890
- prefersReducedMotion
3918
+ prefersReducedMotion,
3919
+ cardRadius
3891
3920
  }) {
3892
3921
  const shimmerStyle = prefersReducedMotion ? { background: tokens.border, opacity: 0.6 } : {
3893
3922
  background: `linear-gradient(90deg, ${tokens.border} 0%, ${tokens.bg} 50%, ${tokens.border} 100%)`,
@@ -3920,7 +3949,7 @@ function LoadingSkeleton({
3920
3949
  "aria-hidden": "true",
3921
3950
  style: {
3922
3951
  padding: 24,
3923
- borderRadius: 12,
3952
+ borderRadius: cardRadius,
3924
3953
  border: `1px solid ${tokens.border}`,
3925
3954
  background: tokens.bg,
3926
3955
  minHeight: 280,
@@ -28,7 +28,7 @@ var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
28
28
  // src/vue/index.ts
29
29
 
30
30
  // src/core/version.ts
31
- var VERSION = "1.0.5";
31
+ var VERSION = "1.0.11";
32
32
 
33
33
  // src/core/AforoEmbed.ts
34
34
  var mountedElements = /* @__PURE__ */ new WeakMap();
@@ -183,6 +183,7 @@ function pricingCardConfigToProps(config) {
183
183
  const theme = readEnum(extra.theme, ["light", "dark", "auto"], "auto");
184
184
  const locale = typeof extra.locale === "string" ? extra.locale : void 0;
185
185
  const maxPlans = typeof extra.maxPlans === "number" && Number.isFinite(extra.maxPlans) ? extra.maxPlans : void 0;
186
+ const borderRadius = typeof extra.borderRadius === "number" && Number.isFinite(extra.borderRadius) ? extra.borderRadius : void 0;
186
187
  const ctaText = typeof extra.ctaText === "string" ? extra.ctaText : void 0;
187
188
  const ctaUrl = typeof extra.ctaUrl === "string" ? extra.ctaUrl : void 0;
188
189
  const showFeatures = typeof extra.showFeatures === "boolean" ? extra.showFeatures : void 0;
@@ -196,6 +197,7 @@ function pricingCardConfigToProps(config) {
196
197
  theme,
197
198
  locale,
198
199
  maxPlans,
200
+ borderRadius,
199
201
  showFeatures,
200
202
  ctaText,
201
203
  ctaUrl,
@@ -887,8 +889,9 @@ var _BridgeClient = class _BridgeClient {
887
889
  }
888
890
  if (!resp.ok) return emptyPage;
889
891
  try {
890
- const body = await resp.json();
891
- if (!body || typeof body !== "object") return emptyPage;
892
+ const raw = await resp.json();
893
+ if (!raw || typeof raw !== "object") return emptyPage;
894
+ const body = raw.data ?? raw;
892
895
  return {
893
896
  content: Array.isArray(body.content) ? body.content : [],
894
897
  totalElements: typeof body.totalElements === "number" && Number.isFinite(body.totalElements) ? body.totalElements : 0,
@@ -931,7 +934,8 @@ var _BridgeClient = class _BridgeClient {
931
934
  }
932
935
  if (!resp.ok) return null;
933
936
  try {
934
- const body = await resp.json();
937
+ const raw = await resp.json();
938
+ const body = raw ? raw.data ?? raw : null;
935
939
  if (!body || typeof body.downloadUrl !== "string" || body.downloadUrl.length === 0) {
936
940
  return null;
937
941
  }
@@ -1020,7 +1024,8 @@ var _BridgeClient = class _BridgeClient {
1020
1024
  }
1021
1025
  let body;
1022
1026
  try {
1023
- body = await resp.json();
1027
+ const raw = await resp.json();
1028
+ body = raw?.data ?? raw;
1024
1029
  } catch {
1025
1030
  throw new BridgeClientError(
1026
1031
  "Malformed invoice-payment-initiate response (not JSON)",
@@ -1331,9 +1336,9 @@ var _BridgeClient = class _BridgeClient {
1331
1336
  if (!resp.ok) {
1332
1337
  throw await this.parseError(resp);
1333
1338
  }
1334
- let body;
1339
+ let raw;
1335
1340
  try {
1336
- body = await resp.json();
1341
+ raw = await resp.json();
1337
1342
  } catch {
1338
1343
  throw new BridgeClientError(
1339
1344
  "Malformed confirmCart response (not JSON)",
@@ -1342,6 +1347,7 @@ var _BridgeClient = class _BridgeClient {
1342
1347
  false
1343
1348
  );
1344
1349
  }
1350
+ const body = raw?.data ?? raw ?? {};
1345
1351
  if (!body.cartId || !body.status) {
1346
1352
  throw new BridgeClientError(
1347
1353
  "Malformed confirmCart response (missing required fields)",
@@ -1406,9 +1412,9 @@ var _BridgeClient = class _BridgeClient {
1406
1412
  * undefined access.
1407
1413
  */
1408
1414
  async parseCartResponse(resp, methodName) {
1409
- let body;
1415
+ let raw;
1410
1416
  try {
1411
- body = await resp.json();
1417
+ raw = await resp.json();
1412
1418
  } catch {
1413
1419
  throw new BridgeClientError(
1414
1420
  `Malformed ${methodName} response (not JSON)`,
@@ -1417,7 +1423,8 @@ var _BridgeClient = class _BridgeClient {
1417
1423
  false
1418
1424
  );
1419
1425
  }
1420
- if (!body.cartId || !body.cartType || !body.status || !body.targetId) {
1426
+ const data = raw?.data ?? raw ?? {};
1427
+ if (!data.cartId || !data.cartType || !data.status || !data.targetId) {
1421
1428
  throw new BridgeClientError(
1422
1429
  `Malformed ${methodName} response (missing required fields)`,
1423
1430
  500,
@@ -1426,21 +1433,21 @@ var _BridgeClient = class _BridgeClient {
1426
1433
  );
1427
1434
  }
1428
1435
  return {
1429
- cartId: body.cartId,
1430
- cartType: body.cartType,
1431
- targetId: body.targetId,
1432
- status: body.status,
1433
- totalCents: typeof body.totalCents === "number" && Number.isFinite(body.totalCents) ? body.totalCents : 0,
1434
- currency: typeof body.currency === "string" ? body.currency : "USD",
1435
- gatewayProvider: body.gatewayProvider ?? null,
1436
- gatewayClientSecret: body.gatewayClientSecret ?? null,
1437
- gatewayOrderId: body.gatewayOrderId ?? null,
1438
- gatewayApprovalUrl: body.gatewayApprovalUrl ?? null,
1439
- gatewaySandboxMode: body.gatewaySandboxMode ?? null,
1440
- subscriptionId: body.subscriptionId ?? null,
1441
- invoiceId: body.invoiceId ?? null,
1442
- expiresAt: typeof body.expiresAt === "string" ? body.expiresAt : (/* @__PURE__ */ new Date(0)).toISOString(),
1443
- completedAt: body.completedAt ?? null
1436
+ cartId: data.cartId,
1437
+ cartType: data.cartType,
1438
+ targetId: data.targetId,
1439
+ status: data.status,
1440
+ totalCents: typeof data.totalCents === "number" && Number.isFinite(data.totalCents) ? data.totalCents : 0,
1441
+ currency: typeof data.currency === "string" ? data.currency : "USD",
1442
+ gatewayProvider: data.gatewayProvider ?? null,
1443
+ gatewayClientSecret: data.gatewayClientSecret ?? null,
1444
+ gatewayOrderId: data.gatewayOrderId ?? null,
1445
+ gatewayApprovalUrl: data.gatewayApprovalUrl ?? null,
1446
+ gatewaySandboxMode: data.gatewaySandboxMode ?? null,
1447
+ subscriptionId: data.subscriptionId ?? null,
1448
+ invoiceId: data.invoiceId ?? null,
1449
+ expiresAt: typeof data.expiresAt === "string" ? data.expiresAt : (/* @__PURE__ */ new Date(0)).toISOString(),
1450
+ completedAt: data.completedAt ?? null
1444
1451
  };
1445
1452
  }
1446
1453
  /** Public liveness probe. Returns null on failure (not an error). */
@@ -1801,14 +1808,17 @@ var _BridgeClient = class _BridgeClient {
1801
1808
  idempotencyKey,
1802
1809
  sessionJwt
1803
1810
  }),
1804
- body: JSON.stringify(request)
1811
+ // 2026-08-29 fix: same bug as cancelSubscription() below — EmbedUpgradeRequest
1812
+ // requires idempotencyKey as a @NotBlank BODY field, but this only ever sent
1813
+ // it via the Idempotency-Key header.
1814
+ body: JSON.stringify({ ...request, idempotencyKey })
1805
1815
  });
1806
1816
  if (!resp.ok) {
1807
1817
  throw await this.parseError(resp);
1808
1818
  }
1809
- let body;
1819
+ let raw;
1810
1820
  try {
1811
- body = await resp.json();
1821
+ raw = await resp.json();
1812
1822
  } catch {
1813
1823
  throw new BridgeClientError(
1814
1824
  "Malformed upgrade response (not JSON)",
@@ -1817,6 +1827,7 @@ var _BridgeClient = class _BridgeClient {
1817
1827
  false
1818
1828
  );
1819
1829
  }
1830
+ const body = raw ? raw.data ?? raw : {};
1820
1831
  if (!body.subscriptionId || !body.previousOfferingId || !body.newOfferingId || !body.status) {
1821
1832
  throw new BridgeClientError(
1822
1833
  "Malformed upgrade response (missing required fields)",
@@ -1880,14 +1891,19 @@ var _BridgeClient = class _BridgeClient {
1880
1891
  idempotencyKey,
1881
1892
  sessionJwt
1882
1893
  }),
1883
- body: JSON.stringify(request)
1894
+ // 2026-08-29 fix: EmbedCancelRequest (storefront-service) requires
1895
+ // idempotencyKey as a @NotBlank BODY field — this only ever sent it
1896
+ // via the Idempotency-Key header, so every real cancellation 400'd
1897
+ // with "idempotencyKey is required" regardless of any other field.
1898
+ // Confirmed live against production.
1899
+ body: JSON.stringify({ ...request, idempotencyKey })
1884
1900
  });
1885
1901
  if (!resp.ok) {
1886
1902
  throw await this.parseError(resp);
1887
1903
  }
1888
- let body;
1904
+ let raw;
1889
1905
  try {
1890
- body = await resp.json();
1906
+ raw = await resp.json();
1891
1907
  } catch {
1892
1908
  throw new BridgeClientError(
1893
1909
  "Malformed cancel response (not JSON)",
@@ -1896,7 +1912,8 @@ var _BridgeClient = class _BridgeClient {
1896
1912
  false
1897
1913
  );
1898
1914
  }
1899
- if (!body.subscriptionId || !body.status || !body.effectiveAt || !body.feedbackId) {
1915
+ const body = raw ? raw.data ?? raw : null;
1916
+ if (!body || !body.subscriptionId || !body.status || !body.effectiveAt) {
1900
1917
  throw new BridgeClientError(
1901
1918
  "Malformed cancel response (missing required fields)",
1902
1919
  500,
@@ -1909,7 +1926,7 @@ var _BridgeClient = class _BridgeClient {
1909
1926
  status: body.status,
1910
1927
  cancelledAt: body.cancelledAt ?? null,
1911
1928
  effectiveAt: body.effectiveAt,
1912
- feedbackId: body.feedbackId,
1929
+ feedbackId: body.feedbackId ?? null,
1913
1930
  creditNoteId: body.creditNoteId ?? null
1914
1931
  };
1915
1932
  }
@@ -1939,7 +1956,8 @@ var _BridgeClient = class _BridgeClient {
1939
1956
  if (!resp.ok) {
1940
1957
  return { methods: [], defaultMethodId: null };
1941
1958
  }
1942
- const body = await resp.json();
1959
+ const raw = await resp.json();
1960
+ const body = raw ? raw.data ?? raw : {};
1943
1961
  return {
1944
1962
  methods: Array.isArray(body.methods) ? body.methods : [],
1945
1963
  defaultMethodId: body.defaultMethodId ?? null
@@ -1969,7 +1987,8 @@ var _BridgeClient = class _BridgeClient {
1969
1987
  body: JSON.stringify({})
1970
1988
  });
1971
1989
  if (!resp.ok) return null;
1972
- const body = await resp.json();
1990
+ const raw = await resp.json();
1991
+ const body = raw ? raw.data ?? raw : {};
1973
1992
  if (!body.clientSecret) return null;
1974
1993
  return {
1975
1994
  clientSecret: body.clientSecret,
@@ -3049,6 +3068,7 @@ function WidgetShell(props) {
3049
3068
  var DEFAULT_LAYOUT = "horizontal";
3050
3069
  var DEFAULT_MAX_PLANS = 4;
3051
3070
  var DEFAULT_CTA_TEXT = "Get Started";
3071
+ var DEFAULT_CARD_RADIUS = 12;
3052
3072
  function clampLayout(raw) {
3053
3073
  return raw === "horizontal" || raw === "vertical" || raw === "table" ? raw : void 0;
3054
3074
  }
@@ -3059,7 +3079,7 @@ function setTenantDefaultsIdempotent(setter, next) {
3059
3079
  setter((prev) => {
3060
3080
  if (prev === next) return prev;
3061
3081
  if (!prev && !next) return prev;
3062
- if (prev && next && prev.layout === next.layout && prev.theme === next.theme && prev.maxPlans === next.maxPlans && prev.showFeatures === next.showFeatures && prev.ctaText === next.ctaText) {
3082
+ if (prev && next && prev.layout === next.layout && prev.theme === next.theme && prev.maxPlans === next.maxPlans && prev.showFeatures === next.showFeatures && prev.ctaText === next.ctaText && prev.borderRadius === next.borderRadius) {
3063
3083
  return prev;
3064
3084
  }
3065
3085
  return next;
@@ -3074,7 +3094,8 @@ function extractTenantDefaults(config) {
3074
3094
  theme: typeof raw.theme === "string" ? raw.theme : void 0,
3075
3095
  maxPlans: typeof raw.maxPlans === "number" && Number.isFinite(raw.maxPlans) ? raw.maxPlans : void 0,
3076
3096
  showFeatures: typeof raw.showFeatures === "boolean" ? raw.showFeatures : void 0,
3077
- ctaText: typeof raw.ctaText === "string" && raw.ctaText.length > 0 ? raw.ctaText : void 0
3097
+ ctaText: typeof raw.ctaText === "string" && raw.ctaText.length > 0 ? raw.ctaText : void 0,
3098
+ borderRadius: typeof raw.borderRadius === "number" && Number.isFinite(raw.borderRadius) ? raw.borderRadius : void 0
3078
3099
  };
3079
3100
  }
3080
3101
  var DARK_TOKEN_OVERLAY = {
@@ -3196,6 +3217,7 @@ function PricingCardBody(props) {
3196
3217
  theme: themeProp,
3197
3218
  locale: localeProp,
3198
3219
  maxPlans: maxPlansProp,
3220
+ borderRadius: borderRadiusProp,
3199
3221
  showFeatures: showFeaturesProp,
3200
3222
  ctaText: ctaTextProp,
3201
3223
  ctaUrl: ctaUrlProp,
@@ -3209,6 +3231,7 @@ function PricingCardBody(props) {
3209
3231
  const maxPlans = typeof maxPlansProp === "number" && Number.isFinite(maxPlansProp) ? maxPlansProp : typeof tenantDefaults?.maxPlans === "number" && Number.isFinite(tenantDefaults.maxPlans) ? tenantDefaults.maxPlans : DEFAULT_MAX_PLANS;
3210
3232
  const showFeatures = typeof showFeaturesProp === "boolean" ? showFeaturesProp : typeof tenantDefaults?.showFeatures === "boolean" ? tenantDefaults.showFeatures : true;
3211
3233
  const ctaTextEffective = ctaTextProp ?? tenantDefaults?.ctaText ?? void 0;
3234
+ const cardRadius = typeof borderRadiusProp === "number" && Number.isFinite(borderRadiusProp) ? borderRadiusProp : typeof tenantDefaults?.borderRadius === "number" && Number.isFinite(tenantDefaults.borderRadius) ? tenantDefaults.borderRadius : DEFAULT_CARD_RADIUS;
3212
3235
  const shell = useWidgetShell();
3213
3236
  const { tokens: shellTokens, bridgeClient, telemetry, bus, tenantSlug } = shell;
3214
3237
  const isDark = React7__namespace.useMemo(() => {
@@ -3426,7 +3449,8 @@ function PricingCardBody(props) {
3426
3449
  {
3427
3450
  layout,
3428
3451
  tokens,
3429
- prefersReducedMotion
3452
+ prefersReducedMotion,
3453
+ cardRadius
3430
3454
  }
3431
3455
  )
3432
3456
  }
@@ -3498,7 +3522,8 @@ function PricingCardBody(props) {
3498
3522
  ctaTextProp: ctaTextEffective,
3499
3523
  featuredOverride: featuredOfferingId,
3500
3524
  onCtaClick: handleCtaClick,
3501
- intlOverride
3525
+ intlOverride,
3526
+ cardRadius
3502
3527
  }
3503
3528
  )
3504
3529
  }
@@ -3513,7 +3538,8 @@ function PlanGrid({
3513
3538
  ctaTextProp,
3514
3539
  featuredOverride,
3515
3540
  onCtaClick,
3516
- intlOverride
3541
+ intlOverride,
3542
+ cardRadius
3517
3543
  }) {
3518
3544
  const isHorizontal = layout === "horizontal";
3519
3545
  const gridStyle2 = isHorizontal ? {
@@ -3536,7 +3562,8 @@ function PlanGrid({
3536
3562
  ctaTextProp,
3537
3563
  featured: offeringIsFeatured(o, featuredOverride),
3538
3564
  onCtaClick,
3539
- intlOverride
3565
+ intlOverride,
3566
+ cardRadius
3540
3567
  },
3541
3568
  o.offeringId
3542
3569
  )) });
@@ -3549,7 +3576,8 @@ function PlanCard({
3549
3576
  ctaTextProp,
3550
3577
  featured,
3551
3578
  onCtaClick,
3552
- intlOverride
3579
+ intlOverride,
3580
+ cardRadius
3553
3581
  }) {
3554
3582
  const { text: price, unitSuffix } = resolveDisplayPrice(offering, locale, intlOverride);
3555
3583
  const isContactSales = price === "\u2014";
@@ -3560,7 +3588,7 @@ function PlanCard({
3560
3588
  display: "flex",
3561
3589
  flexDirection: "column",
3562
3590
  padding: 24,
3563
- borderRadius: 12,
3591
+ borderRadius: cardRadius,
3564
3592
  border: featured ? `2px solid ${tokens.primary}` : `1px solid ${tokens.border}`,
3565
3593
  background: tokens.bg,
3566
3594
  color: tokens.text,
@@ -3910,7 +3938,8 @@ function cellAria(label, feature) {
3910
3938
  function LoadingSkeleton({
3911
3939
  layout,
3912
3940
  tokens,
3913
- prefersReducedMotion
3941
+ prefersReducedMotion,
3942
+ cardRadius
3914
3943
  }) {
3915
3944
  const shimmerStyle = prefersReducedMotion ? { background: tokens.border, opacity: 0.6 } : {
3916
3945
  background: `linear-gradient(90deg, ${tokens.border} 0%, ${tokens.bg} 50%, ${tokens.border} 100%)`,
@@ -3943,7 +3972,7 @@ function LoadingSkeleton({
3943
3972
  "aria-hidden": "true",
3944
3973
  style: {
3945
3974
  padding: 24,
3946
- borderRadius: 12,
3975
+ borderRadius: cardRadius,
3947
3976
  border: `1px solid ${tokens.border}`,
3948
3977
  background: tokens.bg,
3949
3978
  minHeight: 280,