@solvapay/react 2.5.0 → 2.6.0-preview-01847ff5f57eafaa4bca393519caeaf6856d968c

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.
@@ -6,7 +6,9 @@
6
6
  * once on `:root` with `light-dark()` so hosts that publish nothing
7
7
  * still get a WCAG-compliant palette, and hosts that publish tokens
8
8
  * win. `html`/`body` stay transparent so the host canvas shows
9
- * through; the card is a hairline frame, not a filled sheet.
9
+ * through. The host owns the outer frame (`prefersBorder: true`):
10
+ * the widget root and the surface card paint no border, fill, or
11
+ * radius, so a framing host never nests a second card around ours.
10
12
  *
11
13
  * All classes start with `solvapay-mcp-` so they don't collide with the
12
14
  * core `@solvapay/react` styles or with integrator-supplied classes.
@@ -69,17 +71,31 @@ body {
69
71
  line-height: 1.5;
70
72
  }
71
73
 
74
+ /* Inline frames are sized to the content by the host (`size-changed`),
75
+ * so the root never legitimately scrolls. When a view grows in place
76
+ * the document overflows for one frame, the root gains a classic
77
+ * vertical scrollbar, and Chromium (Claude Desktop) can keep that
78
+ * scrollbar after the host has grown the frame: a thumbless 15px track
79
+ * that still steals layout width. No root scrollbar, ever; wheel and
80
+ * touch scrolling still work on hosts that cap the frame height.
81
+ * Fullscreen scrolls on `.solvapay-mcp-main`, which keeps its own bar. */
82
+ html {
83
+ scrollbar-width: none;
84
+ }
85
+
86
+ /* No gutter: root padding comes only from `hostContext.safeAreaInsets`,
87
+ * applied to `.solvapay-mcp-main` by the display-mode hook. */
72
88
  #root {
73
89
  min-height: 100%;
74
- padding: 16px;
75
90
  }
76
91
 
77
92
  /* Fill the host container. Anthropic: "Apps always fill the
78
93
  * container width — there are no fixed breakpoints." `main` stays
79
94
  * `width: 100%` so `@container mcp (min-width: 760px)` sees the
80
- * host. The visual widget — chrome, loading card, shell — is one
81
- * centered 760px block (no-op below that width). Fullscreen lifts
82
- * the cap and becomes a centered 1000px hosted column. */
95
+ * host. Chrome, loading card and shell fill it too: the host draws
96
+ * its frame at the full column width, so any inline cap on our side
97
+ * shows up as dead margins inside that frame (seen on Claude Desktop
98
+ * past 760px). Fullscreen becomes a centered 1000px hosted column. */
83
99
  .solvapay-mcp-main {
84
100
  --solvapay-surface: var(--color-background-primary);
85
101
  --solvapay-muted: var(--color-background-secondary);
@@ -128,8 +144,6 @@ body {
128
144
  .solvapay-mcp-main > .solvapay-mcp-card,
129
145
  .solvapay-mcp-shell {
130
146
  width: 100%;
131
- max-inline-size: 760px;
132
- margin-inline: auto;
133
147
  }
134
148
 
135
149
  .solvapay-mcp-chrome-row {
@@ -149,9 +163,7 @@ body {
149
163
  flex-direction: column;
150
164
  gap: var(--solvapay-section-gap);
151
165
  padding: var(--solvapay-card-padding);
152
- /* Hairline frame only — no fill, no shadow. Host tokens win. */
153
- border-radius: var(--border-radius-xl);
154
- border: 1px solid var(--color-border-primary);
166
+ /* A padded section, not a frame — the host card is the frame. */
155
167
  transition: opacity 180ms ease;
156
168
  }
157
169
 
@@ -227,7 +239,7 @@ body {
227
239
 
228
240
  /*
229
241
  * Subtle feedback while a background `check_purchase` poll is in flight.
230
- * The card frame stays mounted — we just dim it so the user sees activity
242
+ * The card stays mounted — we just dim it so the user sees activity
231
243
  * without any layout shift or content swap.
232
244
  */
233
245
  .solvapay-mcp-card[data-refreshing='true'] {
@@ -286,6 +298,10 @@ body {
286
298
  font-size: 13px;
287
299
  }
288
300
 
301
+ .solvapay-mcp-signed-in-ref {
302
+ font-family: var(--font-mono);
303
+ }
304
+
289
305
  .solvapay-mcp-notice {
290
306
  padding: 12px;
291
307
  border-radius: var(--border-radius-md);
@@ -389,12 +405,11 @@ body {
389
405
  /* Account view */
390
406
 
391
407
  /* `<CurrentPlanCard>` ships its own card frame for standalone web
392
- * surfaces. Inside the MCP account view the surrounding
393
- * `.solvapay-mcp-card` already IS the frame, so the default chrome
394
- * nested a second bordered box and doubled the inset (16px card
395
- * padding + 16px card padding). Flatten it: the plan facts then align
396
- * to the same left edge and 16px gutter as the heading, the CTA, and
397
- * every other MCP surface (checkout, topup, success). */
408
+ * surfaces. Inside the MCP account view the host card is the frame,
409
+ * so the default chrome would nest a second bordered box and double
410
+ * the inset. Flatten it: the plan facts then align to the same left
411
+ * edge as the heading, the CTA, and every other MCP surface
412
+ * (checkout, topup, success). */
398
413
  .solvapay-mcp-account [data-solvapay-current-plan-card] {
399
414
  padding: 0;
400
415
  border: 0;
@@ -461,48 +476,6 @@ body {
461
476
  gap: 12px;
462
477
  }
463
478
 
464
- /* Rounded-rectangle quick-amount chips. Mirrors the `.solvapay-amount-picker-pill`
465
- * shape used by the web SDK and the hosted topup page so the topup look is
466
- * consistent across surfaces. Colors come from host theme tokens
467
- * (`--color-*`) so Claude Desktop / ChatGPT / VSCode dark themes adapt
468
- * automatically. */
469
- .solvapay-mcp-amount-options {
470
- display: flex;
471
- flex-wrap: wrap;
472
- gap: 8px;
473
- }
474
-
475
- .solvapay-mcp-amount-option {
476
- padding: 6px 14px;
477
- border-radius: var(--border-radius-md);
478
- border: 1px solid var(--color-border-primary);
479
- background: transparent;
480
- color: var(--color-text-primary);
481
- font-size: 13px;
482
- font-weight: 500;
483
- cursor: pointer;
484
- transition:
485
- background-color 120ms ease,
486
- border-color 120ms ease;
487
- }
488
-
489
- /* Recommended chip: a subtly heavier border on the default state. No
490
- * color — stays within the pre-refactor black/white/gray palette. The
491
- * selected state below still wins and fills the chip with the accent. */
492
- .solvapay-mcp-amount-option[data-popular]:not([data-state='selected']) {
493
- border-color: var(--color-text-primary);
494
- }
495
-
496
- .solvapay-mcp-amount-option:hover:not([data-state='selected']):not(:disabled) {
497
- background: var(--solvapay-control-hover);
498
- }
499
-
500
- .solvapay-mcp-amount-option[data-state='selected'] {
501
- border-color: var(--color-background-inverse);
502
- background: var(--color-background-inverse);
503
- color: var(--color-text-inverse);
504
- }
505
-
506
479
  /* `.solvapay-mcp-amount-custom` now wraps the bordered row — currency
507
480
  * prefix + input — instead of being applied directly to the `<input>`.
508
481
  * Lets us prefix the merchant currency symbol the same way the hosted
@@ -671,10 +644,11 @@ body {
671
644
  * There is no sidebar grid.
672
645
  */
673
646
 
647
+ /* No gap: the card's own bottom padding is the only space between the
648
+ * last control and the legal footer. */
674
649
  .solvapay-mcp-shell {
675
650
  display: flex;
676
651
  flex-direction: column;
677
- gap: 16px;
678
652
  }
679
653
 
680
654
  /* Body column carrying every step of every surface (account card,
@@ -728,14 +702,9 @@ body {
728
702
  display: none;
729
703
  }
730
704
 
731
- .solvapay-mcp-main[data-display-mode='fullscreen'] > .solvapay-mcp-card {
732
- max-inline-size: none;
733
- }
734
-
735
705
  .solvapay-mcp-main[data-display-mode='fullscreen']
736
706
  .solvapay-mcp-card:has(.solvapay-mcp-hosted-layout) {
737
707
  padding: 0;
738
- border: none;
739
708
  }
740
709
 
741
710
  html:has(.solvapay-mcp-main[data-display-mode='fullscreen']),
@@ -746,7 +715,6 @@ html:has(.solvapay-mcp-main[data-display-mode='fullscreen']) #root {
746
715
  }
747
716
 
748
717
  html:has(.solvapay-mcp-main[data-display-mode='fullscreen']) #root {
749
- padding: 0;
750
718
  overflow: hidden;
751
719
  }
752
720
 
@@ -757,7 +725,6 @@ html:has(.solvapay-mcp-main[data-display-mode='fullscreen']) #root {
757
725
  /* 1000px column + the 72px gutter on each side. */
758
726
  max-inline-size: 1144px;
759
727
  padding: 56px 72px 40px;
760
- margin-inline: 0;
761
728
  }
762
729
 
763
730
  .solvapay-mcp-hosted-layout {
@@ -810,42 +777,44 @@ html:has(.solvapay-mcp-main[data-display-mode='fullscreen']) #root {
810
777
  /*
811
778
  * Shell-level legal footer.
812
779
  *
813
- * Lays the `<LegalFooter>` primitive out as one centered line:
814
- * `Provided by SolvaPay · Terms · Privacy`. The parent
815
- * `.solvapay-mcp-shell` already supplies a `gap: 16px` between
816
- * children, so the row needs no extra `padding-top` of its own.
780
+ * One centered, muted line: `Provided by SolvaPay Terms Privacy`.
781
+ * The attribution is plain text, not a link. The `<LegalFooter>`
782
+ * wrappers flatten via `display: contents` so the attribution and both
783
+ * links share one flex gap, and the primitive's `·` separators are
784
+ * hidden. The card's bottom padding is the only space above it; the
785
+ * footer carries its own bottom inset so it does not sit flush against
786
+ * the host frame.
817
787
  *
818
- * Scoped to the shell context so the primitive's default centred
819
- * column layout, font size, and muted slate-500 ink keep working for
820
- * any other consumer who drops the primitive in.
788
+ * Scoped to the shell context so the primitive's default layout keeps
789
+ * working for any other consumer who drops it in.
821
790
  */
822
791
  .solvapay-mcp-shell-footer {
792
+ display: flex;
793
+ justify-content: center;
794
+ align-items: baseline;
795
+ gap: 1rem;
823
796
  font-size: 12px;
797
+ padding: 0 var(--solvapay-card-padding) 16px;
798
+ }
799
+
800
+ /* Fullscreen zeroes the card padding, so the footer supplies its own
801
+ * gap above; the shell's 40px bottom padding handles the space below. */
802
+ .solvapay-mcp-main[data-display-mode='fullscreen'] .solvapay-mcp-shell-footer {
803
+ padding: 16px 0 0;
824
804
  }
825
805
 
806
+ .solvapay-mcp-shell-footer [data-solvapay-legal-footer],
807
+ .solvapay-mcp-shell-footer [data-solvapay-legal-footer-links] {
808
+ display: contents;
809
+ }
810
+
811
+ /* The shared footer sizes in `rem`; the widget root is 14px, not 16px. */
826
812
  .solvapay-mcp-shell-footer [data-solvapay-legal-footer] {
827
- flex-direction: row-reverse;
828
- justify-content: center;
829
- align-items: baseline;
830
- gap: 0;
831
- width: 100%;
832
- /* Step the ink up from slate-500 (the primitive default) to
833
- * slate-600 so the footer reads cleanly against white without
834
- * fading into the card border. Matches the rest of the MCP
835
- * chrome (`AppHeader`, muted body copy). */
836
- color: var(--color-text-secondary);
813
+ font-size: inherit;
837
814
  }
838
815
 
839
- /* Match the visual spacing of the inner `Terms · Privacy` separator.
840
- * That span sits inside an `inline-flex` with `gap: 0.5rem`, so each
841
- * side of its `·` reads as `0.5rem` flex-gap + the literal space in
842
- * the span text. We mirror that by adding `0.5rem` of padding to each
843
- * side of the `::after`-rendered bullet — the existing `' · '` text
844
- * already contributes the matching literal spaces. */
845
- .solvapay-mcp-shell-footer [data-solvapay-legal-footer-attribution]::after {
846
- content: ' · ';
847
- padding: 0 0.5rem;
848
- font-weight: 400;
816
+ .solvapay-mcp-shell-footer [data-solvapay-legal-footer-separator] {
817
+ display: none;
849
818
  }
850
819
 
851
820
  .solvapay-mcp-account {
@@ -998,6 +998,7 @@ var enCopy = {
998
998
  soldBy: "Sold by {merchant}",
999
999
  fullHistory: "Full history",
1000
1000
  fullAccount: "Full account",
1001
+ signedInAs: "Signed in as",
1001
1002
  creditActivityEyebrow: "Credit activity",
1002
1003
  chargesEyebrow: "Charges for this product",
1003
1004
  creditActivityCaption: "Every credit event on your account, newest first, including other products and top-ups. Credits are shared, so the balance only makes sense account-wide.",
@@ -2755,7 +2756,7 @@ var LegalFooter = (0, import_react13.forwardRef)(
2755
2756
  children: copy.legalFooter.terms
2756
2757
  }
2757
2758
  ),
2758
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "aria-hidden": "true", children: " \xB7 " }),
2759
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-solvapay-legal-footer-separator": "", "aria-hidden": "true", children: " \xB7 " }),
2759
2760
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2760
2761
  "a",
2761
2762
  {
@@ -8432,7 +8433,7 @@ var import_core9 = require("@solvapay/core");
8432
8433
 
8433
8434
  // src/utils/isPayg.ts
8434
8435
  function isPaygPlan(plan) {
8435
- return plan?.type === "usage-based" || plan?.type === "hybrid";
8436
+ return plan?.type === "usage-based";
8436
8437
  }
8437
8438
 
8438
8439
  // src/primitives/checkout/shared.ts
@@ -8555,6 +8556,7 @@ function useCheckoutFlow(opts) {
8555
8556
  const planCtx = usePlanSelector();
8556
8557
  const planSelection = usePlanSelection();
8557
8558
  const transport = useTransport();
8559
+ const copy = useCopy();
8558
8560
  const locale = useLocale();
8559
8561
  const balance = useBalance();
8560
8562
  const { creditsPerMinorUnit, displayExchangeRate, adjustBalance } = balance;
@@ -8610,7 +8612,23 @@ function useCheckoutFlow(opts) {
8610
8612
  setError(null);
8611
8613
  setStatus("activating");
8612
8614
  try {
8613
- await transport.activatePlan({ productRef, planRef: selectedPlanRef });
8615
+ const result = await transport.activatePlan({ productRef, planRef: selectedPlanRef });
8616
+ switch (result.status) {
8617
+ case "activated":
8618
+ case "already_active":
8619
+ case "already_purchased":
8620
+ break;
8621
+ case "topup_required":
8622
+ setStatus("idle");
8623
+ setStep("amount");
8624
+ return true;
8625
+ case "payment_required":
8626
+ throw new Error(copy.activation.paymentRequired);
8627
+ case "invalid":
8628
+ throw new Error(result.message ?? copy.activation.invalidConfiguration);
8629
+ default:
8630
+ throw new Error(copy.activation.unexpectedResponse);
8631
+ }
8614
8632
  const credits = await balance.refetch() ?? balance.credits;
8615
8633
  if (credits == null) {
8616
8634
  throw new Error("Credit balance is unavailable");
@@ -8636,7 +8654,17 @@ function useCheckoutFlow(opts) {
8636
8654
  onErrorRef.current?.(wrapped, "activate");
8637
8655
  return false;
8638
8656
  }
8639
- }, [balance, locale, productRef, selectedPlanRef, selectedPlanShape, transport]);
8657
+ }, [
8658
+ balance,
8659
+ copy.activation.invalidConfiguration,
8660
+ copy.activation.paymentRequired,
8661
+ copy.activation.unexpectedResponse,
8662
+ locale,
8663
+ productRef,
8664
+ selectedPlanRef,
8665
+ selectedPlanShape,
8666
+ transport
8667
+ ]);
8640
8668
  const advanceFromPlan = (0, import_react39.useCallback)(async () => {
8641
8669
  if (!selectedPlanShape || !selectedPlanRef) return;
8642
8670
  if (branch === "payg") {
@@ -8674,7 +8702,15 @@ function useCheckoutFlow(opts) {
8674
8702
  }
8675
8703
  setError(null);
8676
8704
  setStep("payment");
8677
- }, [balance, branch, locale, planCtx.currentPlanRef, runActivate, selectedPlanRef, selectedPlanShape]);
8705
+ }, [
8706
+ balance,
8707
+ branch,
8708
+ locale,
8709
+ planCtx.currentPlanRef,
8710
+ runActivate,
8711
+ selectedPlanRef,
8712
+ selectedPlanShape
8713
+ ]);
8678
8714
  const recordPaygSuccess = (0, import_react39.useCallback)(
8679
8715
  (creditsAddedFromBackend) => {
8680
8716
  if (!selectedPlanShape || selectedAmountMinor == null) return;
@@ -9934,8 +9970,8 @@ function deriveUsage(purchase, limits) {
9934
9970
  const hasFiniteCap = limits.unlimited === false && limits.remaining !== null;
9935
9971
  const remaining = hasFiniteCap ? limits.remaining : null;
9936
9972
  const total = typeof limits.limit === "number" && limits.limit > 0 ? limits.limit : null;
9937
- const used = typeof limits.used === "number" ? limits.used : total !== null && remaining !== null ? Math.max(0, total - remaining) : typeof usage?.used === "number" ? usage.used : 0;
9938
- const percentUsed = total !== null && total > 0 ? Math.min(100, Math.round(used / total * 1e4) / 100) : null;
9973
+ const used = typeof limits.used === "number" ? limits.used : total !== null && remaining !== null ? Math.max(0, total - remaining) : null;
9974
+ const percentUsed = total !== null && total > 0 && used !== null ? Math.min(100, Math.round(used / total * 1e4) / 100) : null;
9939
9975
  return {
9940
9976
  meterRef: limits.meterName,
9941
9977
  total,
@@ -10127,7 +10163,7 @@ var Label = (0, import_react45.forwardRef)(function UsageMeterLabel({ className,
10127
10163
  );
10128
10164
  }
10129
10165
  const unit = ctx.usage.meterRef ?? "requests";
10130
- const label = ctx.usage.total !== null ? interpolate(copy.usage.usedLabel, {
10166
+ const label = ctx.usage.total !== null && ctx.usage.used !== null ? interpolate(copy.usage.usedLabel, {
10131
10167
  used: String(ctx.usage.used),
10132
10168
  total: String(ctx.usage.total),
10133
10169
  unit
@@ -1,13 +1,13 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React, { Ref } from 'react';
3
- import { b as Plan, z as Product, s as UseTopupAmountSelectorReturn, y as PurchaseInfo, T as TopupFormProps, c as SaveAutoRechargeResponse, u as AutoRechargeConfig } from '../useUsage-DwwQ-jAO.cjs';
4
- export { B as BootstrapPlanLike, E as CheckoutStep, O as SuccessMeta } from '../useUsage-DwwQ-jAO.cjs';
3
+ import { b as Plan, z as Product, s as UseTopupAmountSelectorReturn, y as PurchaseInfo, T as TopupFormProps, c as SaveAutoRechargeResponse, u as AutoRechargeConfig } from '../useUsage-CPlXBdC5.cjs';
4
+ export { B as BootstrapPlanLike, E as CheckoutStep, O as SuccessMeta } from '../useUsage-CPlXBdC5.cjs';
5
5
  import { TaxBreakdown, BusinessDetailsInput } from '@solvapay/core';
6
- import { A as AutoRechargeInputPayload, F as AmountInputUnit, G as AutoRechargeFormState, l as PaywallStructuredContent } from '../index-B8rb25FF.cjs';
7
- export { H as ActivationFlow, I as ActivationFlowActivateButton, J as ActivationFlowActivated, K as ActivationFlowAmountPicker, L as ActivationFlowContinueButton, N as ActivationFlowError, O as ActivationFlowLoading, Q as ActivationFlowRetrying, R as ActivationFlowRoot, m as ActivationFlowStep, S as ActivationFlowSummary, B as BalanceBadge, n as CancelPlanButton, p as CheckoutStatus, q as CheckoutSteps, T as CheckoutStepsAmountContinueButton, V as CheckoutStepsAmountPicker, W as CheckoutStepsBackLink, X as CheckoutStepsIfStep, Y as CheckoutStepsPayment, Z as CheckoutStepsPlanContinueButton, _ as CheckoutStepsPlanGrid, $ as CheckoutStepsRoot, a0 as CheckoutStepsStepHeading, a1 as CheckoutStepsStepMessage, a2 as CheckoutStepsSuccess, M as MandateText, t as MandateTextProps, a3 as PaymentForm, j as PaymentFormBusinessDetails, c as PaymentFormCardElement, a as PaymentFormCustomerFields, h as PaymentFormError, i as PaymentFormLegalFooter, g as PaymentFormLoading, d as PaymentFormMandateText, b as PaymentFormPaymentElement, a4 as PaymentFormRoot, f as PaymentFormSubmitButton, P as PaymentFormSummary, k as PaymentFormTaxSummary, e as PaymentFormTermsCheckbox, u as PlanBadge, v as ProductBadge, w as PurchaseGate, a5 as PurchaseGateAllowed, a6 as PurchaseGateBlocked, a7 as PurchaseGateError, a8 as PurchaseGateLoading, a9 as PurchaseGateRoot, aa as useActivationFlow, E as useCheckoutStepsContext, ab as usePurchaseGate } from '../index-B8rb25FF.cjs';
6
+ import { A as AutoRechargeInputPayload, F as AmountInputUnit, G as AutoRechargeFormState, l as PaywallStructuredContent } from '../index-CCNxvSm-.cjs';
7
+ export { H as ActivationFlow, I as ActivationFlowActivateButton, J as ActivationFlowActivated, K as ActivationFlowAmountPicker, L as ActivationFlowContinueButton, N as ActivationFlowError, O as ActivationFlowLoading, Q as ActivationFlowRetrying, R as ActivationFlowRoot, m as ActivationFlowStep, S as ActivationFlowSummary, B as BalanceBadge, n as CancelPlanButton, p as CheckoutStatus, q as CheckoutSteps, T as CheckoutStepsAmountContinueButton, V as CheckoutStepsAmountPicker, W as CheckoutStepsBackLink, X as CheckoutStepsIfStep, Y as CheckoutStepsPayment, Z as CheckoutStepsPlanContinueButton, _ as CheckoutStepsPlanGrid, $ as CheckoutStepsRoot, a0 as CheckoutStepsStepHeading, a1 as CheckoutStepsStepMessage, a2 as CheckoutStepsSuccess, M as MandateText, t as MandateTextProps, a3 as PaymentForm, j as PaymentFormBusinessDetails, c as PaymentFormCardElement, a as PaymentFormCustomerFields, h as PaymentFormError, i as PaymentFormLegalFooter, g as PaymentFormLoading, d as PaymentFormMandateText, b as PaymentFormPaymentElement, a4 as PaymentFormRoot, f as PaymentFormSubmitButton, P as PaymentFormSummary, k as PaymentFormTaxSummary, e as PaymentFormTermsCheckbox, u as PlanBadge, v as ProductBadge, w as PurchaseGate, a5 as PurchaseGateAllowed, a6 as PurchaseGateBlocked, a7 as PurchaseGateError, a8 as PurchaseGateLoading, a9 as PurchaseGateRoot, aa as useActivationFlow, E as useCheckoutStepsContext, ab as usePurchaseGate } from '../index-CCNxvSm-.cjs';
8
8
  import { PaymentElement } from '@stripe/react-stripe-js';
9
9
  import { Stripe, StripeElements } from '@stripe/stripe-js';
10
- export { a as UsageMeter, B as UsageMeterBar, b as UsageMeterClassNames, E as UsageMeterEmpty, L as UsageMeterLabel, c as UsageMeterLoading, P as UsageMeterPercentage, R as UsageMeterResetsIn, d as UsageMeterRoot, U as UsageMeterRootProps, u as useUsageMeter } from '../UsageMeter-YX-icS_X.cjs';
10
+ export { a as UsageMeter, B as UsageMeterBar, b as UsageMeterClassNames, E as UsageMeterEmpty, L as UsageMeterLabel, c as UsageMeterLoading, P as UsageMeterPercentage, R as UsageMeterResetsIn, d as UsageMeterRoot, U as UsageMeterRootProps, u as useUsageMeter } from '../UsageMeter-Cxn3_A-q.cjs';
11
11
  import '../adapters/auth.cjs';
12
12
 
13
13
  type PlanPricingOption = {
@@ -1,13 +1,13 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React, { Ref } from 'react';
3
- import { b as Plan, z as Product, s as UseTopupAmountSelectorReturn, y as PurchaseInfo, T as TopupFormProps, c as SaveAutoRechargeResponse, u as AutoRechargeConfig } from '../useUsage-DwFZIuQW.js';
4
- export { B as BootstrapPlanLike, E as CheckoutStep, O as SuccessMeta } from '../useUsage-DwFZIuQW.js';
3
+ import { b as Plan, z as Product, s as UseTopupAmountSelectorReturn, y as PurchaseInfo, T as TopupFormProps, c as SaveAutoRechargeResponse, u as AutoRechargeConfig } from '../useUsage-Bee4D9Hw.js';
4
+ export { B as BootstrapPlanLike, E as CheckoutStep, O as SuccessMeta } from '../useUsage-Bee4D9Hw.js';
5
5
  import { TaxBreakdown, BusinessDetailsInput } from '@solvapay/core';
6
- import { A as AutoRechargeInputPayload, F as AmountInputUnit, G as AutoRechargeFormState, l as PaywallStructuredContent } from '../index-DBd1TLZA.js';
7
- export { H as ActivationFlow, I as ActivationFlowActivateButton, J as ActivationFlowActivated, K as ActivationFlowAmountPicker, L as ActivationFlowContinueButton, N as ActivationFlowError, O as ActivationFlowLoading, Q as ActivationFlowRetrying, R as ActivationFlowRoot, m as ActivationFlowStep, S as ActivationFlowSummary, B as BalanceBadge, n as CancelPlanButton, p as CheckoutStatus, q as CheckoutSteps, T as CheckoutStepsAmountContinueButton, V as CheckoutStepsAmountPicker, W as CheckoutStepsBackLink, X as CheckoutStepsIfStep, Y as CheckoutStepsPayment, Z as CheckoutStepsPlanContinueButton, _ as CheckoutStepsPlanGrid, $ as CheckoutStepsRoot, a0 as CheckoutStepsStepHeading, a1 as CheckoutStepsStepMessage, a2 as CheckoutStepsSuccess, M as MandateText, t as MandateTextProps, a3 as PaymentForm, j as PaymentFormBusinessDetails, c as PaymentFormCardElement, a as PaymentFormCustomerFields, h as PaymentFormError, i as PaymentFormLegalFooter, g as PaymentFormLoading, d as PaymentFormMandateText, b as PaymentFormPaymentElement, a4 as PaymentFormRoot, f as PaymentFormSubmitButton, P as PaymentFormSummary, k as PaymentFormTaxSummary, e as PaymentFormTermsCheckbox, u as PlanBadge, v as ProductBadge, w as PurchaseGate, a5 as PurchaseGateAllowed, a6 as PurchaseGateBlocked, a7 as PurchaseGateError, a8 as PurchaseGateLoading, a9 as PurchaseGateRoot, aa as useActivationFlow, E as useCheckoutStepsContext, ab as usePurchaseGate } from '../index-DBd1TLZA.js';
6
+ import { A as AutoRechargeInputPayload, F as AmountInputUnit, G as AutoRechargeFormState, l as PaywallStructuredContent } from '../index-ykfNzPia.js';
7
+ export { H as ActivationFlow, I as ActivationFlowActivateButton, J as ActivationFlowActivated, K as ActivationFlowAmountPicker, L as ActivationFlowContinueButton, N as ActivationFlowError, O as ActivationFlowLoading, Q as ActivationFlowRetrying, R as ActivationFlowRoot, m as ActivationFlowStep, S as ActivationFlowSummary, B as BalanceBadge, n as CancelPlanButton, p as CheckoutStatus, q as CheckoutSteps, T as CheckoutStepsAmountContinueButton, V as CheckoutStepsAmountPicker, W as CheckoutStepsBackLink, X as CheckoutStepsIfStep, Y as CheckoutStepsPayment, Z as CheckoutStepsPlanContinueButton, _ as CheckoutStepsPlanGrid, $ as CheckoutStepsRoot, a0 as CheckoutStepsStepHeading, a1 as CheckoutStepsStepMessage, a2 as CheckoutStepsSuccess, M as MandateText, t as MandateTextProps, a3 as PaymentForm, j as PaymentFormBusinessDetails, c as PaymentFormCardElement, a as PaymentFormCustomerFields, h as PaymentFormError, i as PaymentFormLegalFooter, g as PaymentFormLoading, d as PaymentFormMandateText, b as PaymentFormPaymentElement, a4 as PaymentFormRoot, f as PaymentFormSubmitButton, P as PaymentFormSummary, k as PaymentFormTaxSummary, e as PaymentFormTermsCheckbox, u as PlanBadge, v as ProductBadge, w as PurchaseGate, a5 as PurchaseGateAllowed, a6 as PurchaseGateBlocked, a7 as PurchaseGateError, a8 as PurchaseGateLoading, a9 as PurchaseGateRoot, aa as useActivationFlow, E as useCheckoutStepsContext, ab as usePurchaseGate } from '../index-ykfNzPia.js';
8
8
  import { PaymentElement } from '@stripe/react-stripe-js';
9
9
  import { Stripe, StripeElements } from '@stripe/stripe-js';
10
- export { a as UsageMeter, B as UsageMeterBar, b as UsageMeterClassNames, E as UsageMeterEmpty, L as UsageMeterLabel, c as UsageMeterLoading, P as UsageMeterPercentage, R as UsageMeterResetsIn, d as UsageMeterRoot, U as UsageMeterRootProps, u as useUsageMeter } from '../UsageMeter-Cg9IAFvV.js';
10
+ export { a as UsageMeter, B as UsageMeterBar, b as UsageMeterClassNames, E as UsageMeterEmpty, L as UsageMeterLabel, c as UsageMeterLoading, P as UsageMeterPercentage, R as UsageMeterResetsIn, d as UsageMeterRoot, U as UsageMeterRootProps, u as useUsageMeter } from '../UsageMeter-sAFkX-Tz.js';
11
11
  import '../adapters/auth.js';
12
12
 
13
13
  type PlanPricingOption = {
@@ -89,7 +89,7 @@ import {
89
89
  useCreditGate,
90
90
  usePaywallNotice,
91
91
  usePurchaseGate
92
- } from "../chunk-IZPE4LKU.js";
92
+ } from "../chunk-SISWCV4B.js";
93
93
  import {
94
94
  AmountPicker,
95
95
  AmountPickerConfirm,
@@ -175,7 +175,7 @@ import {
175
175
  usePlanSelector,
176
176
  useTopupForm,
177
177
  useUsageMeter
178
- } from "../chunk-67GJCZZU.js";
178
+ } from "../chunk-WVWUTOBU.js";
179
179
  import "../chunk-UMXOAUW7.js";
180
180
  import "../chunk-MLKGABMK.js";
181
181
  export {
@@ -1785,8 +1785,20 @@ interface components {
1785
1785
  * @example active
1786
1786
  */
1787
1787
  status: string;
1788
- /** @description Usage billing state for usage-based plans */
1789
- usage?: components['schemas']['UsageBillingDto'];
1788
+ /** @description Billing period of the active usage window; counts come from `/v1/sdk/limits` */
1789
+ usage?: components['schemas']['SdkUsagePeriodDto'];
1790
+ };
1791
+ SdkUsagePeriodDto: {
1792
+ /**
1793
+ * Billing period of the active usage window; counts come from `/v1/sdk/limits`
1794
+ * @example 2025-11-01T00:00:00Z
1795
+ */
1796
+ periodEnd?: string;
1797
+ /**
1798
+ * Billing period of the active usage window; counts come from `/v1/sdk/limits`
1799
+ * @example 2025-10-01T00:00:00Z
1800
+ */
1801
+ periodStart?: string;
1790
1802
  };
1791
1803
  TaxBreakdownDto: {
1792
1804
  /** @description ISO 4217 currency code */
@@ -1934,33 +1946,6 @@ interface components {
1934
1946
  /** @enum {string} */
1935
1947
  taxBehavior?: 'auto' | 'inclusive' | 'exclusive';
1936
1948
  };
1937
- UsageBillingDto: {
1938
- /**
1939
- * Overage cost in cents
1940
- * @example 0
1941
- */
1942
- overageCost: number;
1943
- /**
1944
- * Units exceeding the plan included amount
1945
- * @example 0
1946
- */
1947
- overageUnits: number;
1948
- /**
1949
- * Period end date
1950
- * @example 2025-11-01T00:00:00Z
1951
- */
1952
- periodEnd?: string;
1953
- /**
1954
- * Period start date
1955
- * @example 2025-10-01T00:00:00Z
1956
- */
1957
- periodStart?: string;
1958
- /**
1959
- * Units consumed in current period
1960
- * @example 150
1961
- */
1962
- used: number;
1963
- };
1964
1949
  UsageRecordResponse: {
1965
1950
  creditDebit?: components['schemas']['CreditDebitSuccessResponse'] | components['schemas']['CreditDebitSkippedResponse'];
1966
1951
  /** @example usage_A1B2C3D4 */
@@ -3953,7 +3938,13 @@ interface PurchaseCheckResult {
3953
3938
  interface GetUsageResult {
3954
3939
  meterRef: string | null;
3955
3940
  total: number | null;
3956
- used: number;
3941
+ /**
3942
+ * Consumed units this period. `limits.used` when the backend measured a
3943
+ * finite cap, otherwise `total - remaining` when both are finite.
3944
+ * `null` means this response did not measure consumption (`limits` null,
3945
+ * unlimited, or credit-based).
3946
+ */
3947
+ used: number | null;
3957
3948
  remaining: number | null;
3958
3949
  /** 0–100, rounded to 2dp. `null` when `total` is unknown. */
3959
3950
  percentUsed: number | null;
@@ -4279,6 +4270,8 @@ interface SolvaPayCopy {
4279
4270
  fullHistory: string;
4280
4271
  /** Portal text link. The button adds the external-link glyph. */
4281
4272
  fullAccount: string;
4273
+ /** Inline account identity. Email and customer ref follow the label. */
4274
+ signedInAs: string;
4282
4275
  creditActivityEyebrow: string;
4283
4276
  chargesEyebrow: string;
4284
4277
  creditActivityCaption: string;
@@ -4444,7 +4437,7 @@ interface SolvaPayCopy {
4444
4437
  activationRequiredHeading: string;
4445
4438
  /**
4446
4439
  * Heading for `kind: 'activation_required'` when every available
4447
- * plan is PAYG (`type: 'usage-based' | 'hybrid'`). Displayed as the
4440
+ * plan is PAYG (`type: 'usage-based'`). Displayed as the
4448
4441
  * topup variant of the activation gate so the user sees "Add
4449
4442
  * credits" framing rather than generic "Activate a plan".
4450
4443
  */
@@ -4472,7 +4465,7 @@ interface SolvaPayCopy {
4472
4465
  * Web-friendly copy for the topup variant of an activation gate —
4473
4466
  * `kind: 'activation_required'` where every available plan is
4474
4467
  * PAYG. `<PaywallNotice.Message>` resolves this when the gate's
4475
- * `plans` are all `type: 'usage-based' | 'hybrid'`.
4468
+ * `plans` are all `type: 'usage-based'`.
4476
4469
  */
4477
4470
  topupRequiredMessage: string;
4478
4471
  paymentRequiredProductSuffix: string;
@@ -4571,8 +4564,7 @@ interface TransportLimitsResult {
4571
4564
  needsTopUp?: boolean;
4572
4565
  /**
4573
4566
  * Consumed units this period. Present only when the backend measured
4574
- * a finite cap. Authoritative — do not reconstruct from
4575
- * `purchase.usage.used`.
4567
+ * a finite cap. The purchase wire does not carry a count.
4576
4568
  */
4577
4569
  used?: number;
4578
4570
  /**
@@ -5516,7 +5508,8 @@ interface UseUsageReturn {
5516
5508
  interface UsageSnapshot {
5517
5509
  meterRef: string | null;
5518
5510
  total: number | null;
5519
- used: number;
5511
+ /** Measured consumption, or `null` when this response did not measure it. */
5512
+ used: number | null;
5520
5513
  remaining: number | null;
5521
5514
  percentUsed: number | null;
5522
5515
  periodStart?: string;