@burdenoff/microfe-billing 2026.614.1 → 2026.623.2

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.
Files changed (135) hide show
  1. package/dist/billing/BillingAdminRoutes.js +7 -6
  2. package/dist/billing/BillingAdminRoutes.js.map +1 -1
  3. package/dist/billing/BillingRoot.js +1 -1
  4. package/dist/billing/BillingRoot.js.map +1 -1
  5. package/dist/billing/modules/addons/components/FloatingCartDrawer.js +22 -22
  6. package/dist/billing/modules/addons/components/FloatingCartDrawer.js.map +1 -1
  7. package/dist/billing/modules/addons/pages/AddonCreatePage.js +31 -31
  8. package/dist/billing/modules/addons/pages/AddonCreatePage.js.map +1 -1
  9. package/dist/billing/modules/addons/pages/AddonDetailPage.js +39 -39
  10. package/dist/billing/modules/addons/pages/AddonDetailPage.js.map +1 -1
  11. package/dist/billing/modules/addons/pages/AddonEditPage.js +29 -29
  12. package/dist/billing/modules/addons/pages/AddonEditPage.js.map +1 -1
  13. package/dist/billing/modules/addons/pages/AddonsListPage.js +91 -91
  14. package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
  15. package/dist/billing/modules/analytics/pages/AnalyticsPage.js +40 -40
  16. package/dist/billing/modules/analytics/pages/AnalyticsPage.js.map +1 -1
  17. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +115 -115
  18. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
  19. package/dist/billing/modules/billing/pages/InvoicesListPage.js +75 -72
  20. package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
  21. package/dist/billing/modules/billing/pages/RefundsPage.js +126 -126
  22. package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
  23. package/dist/billing/modules/billing/pages/UserRefundsPage.js +45 -45
  24. package/dist/billing/modules/billing/pages/UserRefundsPage.js.map +1 -1
  25. package/dist/billing/modules/checkout/components/BillingAccountSelector.js +25 -25
  26. package/dist/billing/modules/checkout/components/BillingAccountSelector.js.map +1 -1
  27. package/dist/billing/modules/checkout/components/CompleteBillingAccountModal.js +31 -35
  28. package/dist/billing/modules/checkout/components/CompleteBillingAccountModal.js.map +1 -1
  29. package/dist/billing/modules/checkout/components/CreditsAmountInput.js +9 -9
  30. package/dist/billing/modules/checkout/components/CreditsAmountInput.js.map +1 -1
  31. package/dist/billing/modules/checkout/components/OrderSummary.js +31 -31
  32. package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
  33. package/dist/billing/modules/checkout/components/PromoCodeInput.js +8 -8
  34. package/dist/billing/modules/checkout/components/PromoCodeInput.js.map +1 -1
  35. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js +5 -5
  36. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js.map +1 -1
  37. package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js +9 -9
  38. package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js.map +1 -1
  39. package/dist/billing/modules/checkout/components/StripePaymentForm.js +21 -21
  40. package/dist/billing/modules/checkout/components/StripePaymentForm.js.map +1 -1
  41. package/dist/billing/modules/checkout/components/SubscriptionSelector.js +11 -11
  42. package/dist/billing/modules/checkout/components/SubscriptionSelector.js.map +1 -1
  43. package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js +31 -31
  44. package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js.map +1 -1
  45. package/dist/billing/modules/checkout/components/WorkspaceQuotaAssignmentModal.js +23 -23
  46. package/dist/billing/modules/checkout/components/WorkspaceQuotaAssignmentModal.js.map +1 -1
  47. package/dist/billing/modules/checkout/pages/CheckoutPage.js +91 -91
  48. package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
  49. package/dist/billing/modules/coupons/pages/CouponDetailPage.js +62 -62
  50. package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
  51. package/dist/billing/modules/coupons/pages/CouponsListPage.js +72 -60
  52. package/dist/billing/modules/coupons/pages/CouponsListPage.js.map +1 -1
  53. package/dist/billing/modules/coupons/pages/CreateCouponPage.js +66 -66
  54. package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
  55. package/dist/billing/modules/coupons/pages/EditCouponPage.js +46 -46
  56. package/dist/billing/modules/coupons/pages/EditCouponPage.js.map +1 -1
  57. package/dist/billing/modules/credits/pages/AdminCreditsPage.js +19 -19
  58. package/dist/billing/modules/credits/pages/AdminCreditsPage.js.map +1 -1
  59. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +37 -37
  60. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
  61. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +90 -90
  62. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
  63. package/dist/billing/modules/credits/pages/CreditsPage.js +41 -41
  64. package/dist/billing/modules/credits/pages/CreditsPage.js.map +1 -1
  65. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js +31 -31
  66. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js.map +1 -1
  67. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +35 -35
  68. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
  69. package/dist/billing/modules/dashboard/components/BillingAccountCard.js +24 -24
  70. package/dist/billing/modules/dashboard/components/BillingAccountCard.js.map +1 -1
  71. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js +99 -99
  72. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js.map +1 -1
  73. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js +23 -23
  74. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js.map +1 -1
  75. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +22 -22
  76. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
  77. package/dist/billing/modules/dashboard/pages/OverviewPage.js +58 -58
  78. package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
  79. package/dist/billing/modules/discounts/pages/DiscountsListPage.js +126 -126
  80. package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
  81. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +83 -79
  82. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
  83. package/dist/billing/modules/plans/pages/PlanAssignFreePage.js +16 -16
  84. package/dist/billing/modules/plans/pages/PlanAssignFreePage.js.map +1 -1
  85. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js +40 -40
  86. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js.map +1 -1
  87. package/dist/billing/modules/plans/pages/PlanCreatePage.js +35 -35
  88. package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
  89. package/dist/billing/modules/plans/pages/PlanDetailPage.js +57 -57
  90. package/dist/billing/modules/plans/pages/PlanDetailPage.js.map +1 -1
  91. package/dist/billing/modules/plans/pages/PlanEditPage.js +35 -35
  92. package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
  93. package/dist/billing/modules/plans/pages/PlansBrowsePage.js +57 -57
  94. package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
  95. package/dist/billing/modules/plans/pages/PlansListPage.js +52 -52
  96. package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
  97. package/dist/billing/modules/promotions/pages/CreatePromotionPage.js +40 -39
  98. package/dist/billing/modules/promotions/pages/CreatePromotionPage.js.map +1 -1
  99. package/dist/billing/modules/promotions/pages/PromotionsListPage.js +22 -19
  100. package/dist/billing/modules/promotions/pages/PromotionsListPage.js.map +1 -1
  101. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +34 -34
  102. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
  103. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js +47 -47
  104. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js.map +1 -1
  105. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +39 -39
  106. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
  107. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +52 -52
  108. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
  109. package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js +23 -23
  110. package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js.map +1 -1
  111. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +259 -246
  112. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
  113. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +88 -85
  114. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
  115. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +51 -51
  116. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
  117. package/dist/billing/modules/usage/pages/UsagePage.js +206 -196
  118. package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
  119. package/dist/billing/shared/components/ServerError.js +4 -4
  120. package/dist/billing/shared/components/ServerError.js.map +1 -1
  121. package/dist/billing/shared/components/StatCard.js +11 -33
  122. package/dist/billing/shared/components/StatCard.js.map +1 -1
  123. package/dist/billing/shared/ui/Card.js +15 -0
  124. package/dist/billing/shared/ui/Card.js.map +1 -0
  125. package/dist/billing/shared/ui/MetricCard.js +44 -0
  126. package/dist/billing/shared/ui/MetricCard.js.map +1 -0
  127. package/dist/billing/shared/ui/ProgressBar.js +30 -0
  128. package/dist/billing/shared/ui/ProgressBar.js.map +1 -0
  129. package/dist/billing/shared/ui/SectionHeader.js +2 -0
  130. package/dist/billing/shared/ui/StatusPill.js +28 -0
  131. package/dist/billing/shared/ui/StatusPill.js.map +1 -0
  132. package/dist/billing/shared/ui/index.js +5 -0
  133. package/dist/billing/shared/utils/tokens.js +13 -30
  134. package/dist/billing/shared/utils/tokens.js.map +1 -1
  135. package/package.json +1 -1
@@ -133,15 +133,15 @@ var h = () => new Promise((e, t) => {
133
133
  children: [
134
134
  /* @__PURE__ */ p("div", {
135
135
  className: "flex items-center gap-2",
136
- children: [/* @__PURE__ */ f(u, { className: "size-5 text-primary" }), /* @__PURE__ */ f("span", {
137
- className: "font-medium text-foreground",
136
+ children: [/* @__PURE__ */ f(u, { className: "size-5 text-text-link" }), /* @__PURE__ */ f("span", {
137
+ className: "font-medium text-text-primary",
138
138
  children: "Secure Payment Verification"
139
139
  })]
140
140
  }),
141
141
  D === "processing" && /* @__PURE__ */ p("div", {
142
- className: "p-6 rounded-lg border border-border bg-muted/30 flex flex-col items-center justify-center space-y-3",
143
- children: [/* @__PURE__ */ f(l, { className: "size-8 animate-spin text-primary" }), /* @__PURE__ */ p("p", {
144
- className: "text-sm text-muted-foreground text-center",
142
+ className: "p-6 rounded-lg border border-border-subtle bg-bg-sunken flex flex-col items-center justify-center space-y-3",
143
+ children: [/* @__PURE__ */ f(l, { className: "size-8 animate-spin text-text-link" }), /* @__PURE__ */ p("p", {
144
+ className: "text-sm text-text-secondary text-center",
145
145
  children: [
146
146
  "Confirming payment with your saved card…",
147
147
  /* @__PURE__ */ f("br", {}),
@@ -153,7 +153,7 @@ var h = () => new Promise((e, t) => {
153
153
  })]
154
154
  }),
155
155
  k && /* @__PURE__ */ p("div", {
156
- className: "flex items-center gap-2 p-3 rounded-lg bg-destructive/10 text-destructive text-sm",
156
+ className: "flex items-center gap-2 p-3 rounded-lg bg-status-error-bg-subtle text-status-error-text text-sm",
157
157
  children: [/* @__PURE__ */ f(o, { className: "size-4 shrink-0" }), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("p", {
158
158
  className: "font-medium",
159
159
  children: E("billing.checkout.paymentFailed", "Payment Failed")
@@ -167,7 +167,7 @@ var h = () => new Promise((e, t) => {
167
167
  children: /* @__PURE__ */ f("button", {
168
168
  type: "button",
169
169
  onClick: S,
170
- className: "flex-1 px-4 py-3 rounded-lg border border-border text-foreground font-medium\n hover:bg-muted transition-colors",
170
+ className: "flex-1 px-4 py-3 rounded-lg border border-border-subtle text-text-primary font-medium\n hover:bg-bg-sunken transition-colors",
171
171
  children: "Back to Checkout"
172
172
  })
173
173
  })
@@ -180,12 +180,12 @@ var h = () => new Promise((e, t) => {
180
180
  className: "flex items-center justify-between",
181
181
  children: [/* @__PURE__ */ p("div", {
182
182
  className: "flex items-center gap-2",
183
- children: [/* @__PURE__ */ f(c, { className: "size-5 text-muted-foreground" }), /* @__PURE__ */ f("span", {
184
- className: "font-medium text-foreground",
183
+ children: [/* @__PURE__ */ f(c, { className: "size-5 text-text-secondary" }), /* @__PURE__ */ f("span", {
184
+ className: "font-medium text-text-primary",
185
185
  children: "Card Payment"
186
186
  })]
187
187
  }), /* @__PURE__ */ p("div", {
188
- className: "flex items-center gap-1 text-xs text-muted-foreground",
188
+ className: "flex items-center gap-1 text-xs text-text-secondary",
189
189
  children: [/* @__PURE__ */ f(u, { className: "size-3" }), "Secured by Stripe"]
190
190
  })]
191
191
  }),
@@ -193,14 +193,14 @@ var h = () => new Promise((e, t) => {
193
193
  className: "space-y-2",
194
194
  children: [/* @__PURE__ */ f("div", {
195
195
  ref: L,
196
- className: "min-h-[50px] rounded-lg border border-border bg-background p-4"
196
+ className: "min-h-[50px] rounded-lg border border-border-subtle bg-bg-surface p-4"
197
197
  }), F && /* @__PURE__ */ f("p", {
198
- className: "text-sm text-destructive",
198
+ className: "text-sm text-status-error-text",
199
199
  children: F
200
200
  })]
201
201
  }),
202
202
  k && /* @__PURE__ */ p("div", {
203
- className: "flex items-center gap-2 p-3 rounded-lg bg-destructive/10 text-destructive text-sm",
203
+ className: "flex items-center gap-2 p-3 rounded-lg bg-status-error-bg-subtle text-status-error-text text-sm",
204
204
  children: [/* @__PURE__ */ f(o, { className: "size-4 shrink-0" }), k]
205
205
  }),
206
206
  /* @__PURE__ */ p("div", {
@@ -209,12 +209,12 @@ var h = () => new Promise((e, t) => {
209
209
  type: "button",
210
210
  onClick: S,
211
211
  disabled: D === "processing" || C,
212
- className: "flex-1 px-4 py-3 rounded-lg border border-border text-foreground font-medium\n hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
212
+ className: "flex-1 px-4 py-3 rounded-lg border border-border-subtle text-text-primary font-medium\n hover:bg-bg-sunken disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
213
213
  children: "Cancel"
214
214
  }), /* @__PURE__ */ f("button", {
215
215
  type: "submit",
216
216
  disabled: D === "processing" || C || !N,
217
- className: "flex-1 px-4 py-3 rounded-lg bg-primary text-primary-foreground font-medium\n hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\n flex items-center justify-center gap-2",
217
+ className: "flex-1 px-4 py-3 rounded-lg bg-action-primary-bg text-action-primary-text font-medium\n hover:bg-action-primary-bgHover disabled:opacity-50 disabled:cursor-not-allowed transition-colors\n flex items-center justify-center gap-2",
218
218
  children: D === "processing" ? /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f(l, { className: "size-4 animate-spin" }), "Processing…"] }) : /* @__PURE__ */ p(d, { children: [
219
219
  "Pay",
220
220
  " ",
@@ -226,7 +226,7 @@ var h = () => new Promise((e, t) => {
226
226
  })]
227
227
  }),
228
228
  /* @__PURE__ */ f("p", {
229
- className: "text-center text-xs text-muted-foreground",
229
+ className: "text-center text-xs text-text-secondary",
230
230
  children: "Your payment information is encrypted and secure. We never store your full card details."
231
231
  })
232
232
  ]
@@ -234,14 +234,14 @@ var h = () => new Promise((e, t) => {
234
234
  className: "space-y-4",
235
235
  children: [/* @__PURE__ */ p("div", {
236
236
  className: "flex items-center gap-2",
237
- children: [/* @__PURE__ */ f(c, { className: "size-5 text-muted-foreground" }), /* @__PURE__ */ f("span", {
238
- className: "font-medium text-foreground",
237
+ children: [/* @__PURE__ */ f(c, { className: "size-5 text-text-secondary" }), /* @__PURE__ */ f("span", {
238
+ className: "font-medium text-text-primary",
239
239
  children: E("billing.checkout.cardPayment", "Card Payment")
240
240
  })]
241
241
  }), /* @__PURE__ */ p("div", {
242
- className: "p-6 rounded-lg border border-border bg-muted/30 flex items-center justify-center",
243
- children: [/* @__PURE__ */ f(l, { className: "size-6 animate-spin text-muted-foreground" }), /* @__PURE__ */ f("span", {
244
- className: "ml-2 text-muted-foreground",
242
+ className: "p-6 rounded-lg border border-border-subtle bg-bg-sunken flex items-center justify-center",
243
+ children: [/* @__PURE__ */ f(l, { className: "size-6 animate-spin text-text-secondary" }), /* @__PURE__ */ f("span", {
244
+ className: "ml-2 text-text-secondary",
245
245
  children: E("billing.checkout.loadingPaymentForm", "Loading payment form...")
246
246
  })]
247
247
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"StripePaymentForm.js","names":[],"sources":["../../../../../src/billing/modules/checkout/components/StripePaymentForm.tsx"],"sourcesContent":["/**\n * Stripe Payment Form Component\n * Integrates with Stripe Elements for card payment\n */\n\nimport { type FC, useState, useCallback, useEffect, useRef } from 'react';\nimport { CreditCard, Lock, Loader2, Check, AlertCircle } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { getStripeCardElementStyle, statusTokens } from '../../../shared/utils';\n\n// Stripe types - local definitions to avoid conflicts with external type declarations\ninterface LocalStripeCardElement {\n mount: (element: HTMLElement) => void;\n unmount: () => void;\n destroy: () => void;\n on: (event: string, handler: (event: LocalStripeCardChangeEvent) => void) => void;\n}\n\ninterface LocalStripeCardChangeEvent {\n complete: boolean;\n error?: { message: string };\n}\n\ninterface LocalStripeElements {\n create: (type: 'card', options?: Record<string, unknown>) => LocalStripeCardElement;\n}\n\ninterface LocalStripePaymentMethod {\n id: string;\n card?: {\n last4: string;\n brand: string;\n };\n}\n\ninterface LocalStripeInstance {\n elements: () => LocalStripeElements;\n createPaymentMethod: (options: {\n type: 'card';\n card: LocalStripeCardElement;\n }) => Promise<{ paymentMethod?: LocalStripePaymentMethod; error?: { message: string } }>;\n confirmCardPayment: (\n clientSecret: string,\n options?: { payment_method: string }\n ) => Promise<{\n paymentIntent?: { id: string; status: string };\n error?: { message: string };\n }>;\n}\n\n// Use type assertion when accessing window.Stripe\ntype StripeFactory = (key: string) => LocalStripeInstance;\n\ninterface StripePaymentFormProps {\n clientSecret: string;\n publishableKey: string;\n amount: number;\n currency: string;\n onSuccess: (paymentIntentId: string) => void;\n onError: (error: string) => void;\n onCancel?: () => void;\n disabled?: boolean;\n isCompletingExistingPayment?: boolean; // True for saved cards that need 3D Secure\n}\n\ntype PaymentState = 'idle' | 'loading' | 'processing' | 'success' | 'error';\n\n/**\n * Load Stripe.js SDK dynamically\n */\nconst loadStripeSDK = (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (window.Stripe) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector('script[src=\"https://js.stripe.com/v3/\"]');\n if (existingScript) {\n // Wait for existing script to load\n const checkStripe = setInterval(() => {\n if (window.Stripe) {\n clearInterval(checkStripe);\n resolve();\n }\n }, 100);\n return;\n }\n\n const script = document.createElement('script');\n script.src = 'https://js.stripe.com/v3/';\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('Failed to load Stripe SDK'));\n document.body.appendChild(script);\n });\n};\n\nexport const StripePaymentForm: FC<StripePaymentFormProps> = ({\n clientSecret,\n publishableKey,\n amount,\n currency,\n onSuccess,\n onError,\n onCancel,\n disabled = false,\n isCompletingExistingPayment = false,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const [paymentState, setPaymentState] = useState<PaymentState>('idle');\n const [error, setError] = useState<string | null>(null);\n const [sdkLoaded, setSdkLoaded] = useState(false);\n const [cardComplete, setCardComplete] = useState(false);\n const [cardError, setCardError] = useState<string | null>(null);\n\n const cardElementRef = useRef<HTMLDivElement>(null);\n const stripeRef = useRef<LocalStripeInstance | null>(null);\n const cardElementInstanceRef = useRef<LocalStripeCardElement | null>(null);\n const isMountedRef = useRef(false);\n\n // Load Stripe SDK\n useEffect(() => {\n loadStripeSDK()\n .then(() => {\n setSdkLoaded(true);\n })\n .catch(() => {\n setError('Failed to load payment gateway');\n });\n }, []);\n\n // Initialize Stripe and mount card element (only for new card payments)\n useEffect(() => {\n // Skip card input for completing existing payments (saved cards with 3D Secure)\n if (isCompletingExistingPayment) {\n return;\n }\n\n const windowStripe = (window as unknown as { Stripe?: StripeFactory }).Stripe;\n if (!sdkLoaded || !publishableKey || !windowStripe || isMountedRef.current) {\n return;\n }\n\n // Initialize Stripe\n const stripeInstance = windowStripe(publishableKey);\n stripeRef.current = stripeInstance;\n\n // Create elements\n const elements = stripeInstance.elements();\n const cardElement = elements.create('card', {\n style: getStripeCardElementStyle(),\n });\n cardElementInstanceRef.current = cardElement;\n\n // Mount card element\n if (cardElementRef.current) {\n cardElement.mount(cardElementRef.current);\n isMountedRef.current = true;\n\n // Listen to card element changes\n cardElement.on('change', (event: LocalStripeCardChangeEvent) => {\n setCardError(event.error ? event.error.message : null);\n setCardComplete(event.complete);\n });\n }\n\n // Cleanup\n return () => {\n if (cardElementInstanceRef.current && isMountedRef.current) {\n try {\n cardElementInstanceRef.current.unmount();\n cardElementInstanceRef.current.destroy();\n } catch {\n // Element might already be destroyed\n }\n cardElementInstanceRef.current = null;\n isMountedRef.current = false;\n }\n };\n }, [sdkLoaded, publishableKey, isCompletingExistingPayment]);\n\n // Auto-confirm payment for saved cards (requires 3D Secure or similar action)\n useEffect(() => {\n if (!isCompletingExistingPayment || !sdkLoaded || !publishableKey || paymentState !== 'idle') {\n return;\n }\n\n const confirmExistingPayment = async () => {\n const windowStripe = (window as unknown as { Stripe?: StripeFactory }).Stripe;\n if (!windowStripe) {\n setError('Payment gateway not loaded');\n return;\n }\n\n // Initialize Stripe if not already done\n if (!stripeRef.current) {\n stripeRef.current = windowStripe(publishableKey);\n }\n\n setPaymentState('processing');\n setError(null);\n\n try {\n // Confirm the payment (payment method already attached by backend)\n // This will show 3D Secure popup if needed\n const { paymentIntent, error: confirmError } =\n await stripeRef.current.confirmCardPayment(clientSecret);\n\n if (confirmError) {\n throw new Error(confirmError.message || 'Payment confirmation failed');\n }\n\n if (paymentIntent?.status === 'succeeded') {\n setPaymentState('success');\n onSuccess(paymentIntent.id);\n } else if (paymentIntent?.status === 'processing') {\n setPaymentState('processing');\n // Keep in processing state - webhook will handle completion\n } else {\n throw new Error('Payment was not successful');\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Payment confirmation failed';\n setError(errorMessage);\n setPaymentState('error');\n onError(errorMessage);\n }\n };\n\n confirmExistingPayment();\n }, [\n isCompletingExistingPayment,\n sdkLoaded,\n publishableKey,\n clientSecret,\n paymentState,\n onSuccess,\n onError,\n ]);\n\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n const stripe = stripeRef.current;\n const cardElement = cardElementInstanceRef.current;\n\n if (!stripe || !cardElement) {\n setError('Payment form not ready');\n return;\n }\n\n if (!cardComplete) {\n setCardError('Please enter complete card details');\n return;\n }\n\n setPaymentState('processing');\n setError(null);\n setCardError(null);\n\n try {\n // Step 1: Create PaymentMethod\n const { paymentMethod, error: pmError } = await stripe.createPaymentMethod({\n type: 'card',\n card: cardElement,\n });\n\n if (pmError) {\n throw new Error(pmError.message || 'Failed to create payment method');\n }\n\n if (!paymentMethod) {\n throw new Error('No payment method returned');\n }\n\n // Step 2: Confirm the payment with the client secret\n const { paymentIntent, error: confirmError } = await stripe.confirmCardPayment(\n clientSecret,\n { payment_method: paymentMethod.id }\n );\n\n if (confirmError) {\n throw new Error(confirmError.message || 'Payment failed');\n }\n\n if (paymentIntent?.status === 'succeeded') {\n setPaymentState('success');\n onSuccess(paymentIntent.id);\n } else if (paymentIntent?.status === 'processing') {\n setPaymentState('processing');\n } else {\n throw new Error('Payment was not successful');\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Payment failed';\n setError(errorMessage);\n setPaymentState('error');\n onError(errorMessage);\n }\n },\n [clientSecret, cardComplete, onSuccess, onError]\n );\n\n // Render success state\n if (paymentState === 'success') {\n return (\n <div\n className={`p-6 rounded-lg border ${statusTokens.success.border} ${statusTokens.success.bg}`}\n >\n <div className=\"flex items-center gap-3\">\n <div\n className={`p-2 rounded-full ${statusTokens.success.bg} ${statusTokens.success.icon}`}\n >\n <Check className=\"size-6\" />\n </div>\n <div>\n <h3 className={`font-semibold ${statusTokens.success.text}`}>Payment Successful!</h3>\n <p className={`text-sm ${statusTokens.success.text}`}>\n Your payment has been processed successfully.\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n // Show loading while SDK loads\n if (!sdkLoaded) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2\">\n <CreditCard className=\"size-5 text-muted-foreground\" />\n <span className=\"font-medium text-foreground\">\n {tr('billing.checkout.cardPayment', 'Card Payment')}\n </span>\n </div>\n <div className=\"p-6 rounded-lg border border-border bg-muted/30 flex items-center justify-center\">\n <Loader2 className=\"size-6 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-muted-foreground\">\n {tr('billing.checkout.loadingPaymentForm', 'Loading payment form...')}\n </span>\n </div>\n </div>\n );\n }\n\n // For saved card payments that need confirmation (3D Secure, etc.)\n if (isCompletingExistingPayment) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2\">\n <Lock className=\"size-5 text-primary\" />\n <span className=\"font-medium text-foreground\">Secure Payment Verification</span>\n </div>\n\n {paymentState === 'processing' && (\n <div className=\"p-6 rounded-lg border border-border bg-muted/30 flex flex-col items-center justify-center space-y-3\">\n <Loader2 className=\"size-8 animate-spin text-primary\" />\n <p className=\"text-sm text-muted-foreground text-center\">\n Confirming payment with your saved card…\n <br />\n <span className=\"text-xs\">Please complete any security verification if prompted</span>\n </p>\n </div>\n )}\n\n {error && (\n <div className=\"flex items-center gap-2 p-3 rounded-lg bg-destructive/10 text-destructive text-sm\">\n <AlertCircle className=\"size-4 shrink-0\" />\n <div>\n <p className=\"font-medium\">\n {tr('billing.checkout.paymentFailed', 'Payment Failed')}\n </p>\n <p className=\"text-xs\">{error}</p>\n </div>\n </div>\n )}\n\n {(paymentState === 'error' || error) && onCancel && (\n <div className=\"flex gap-3\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"flex-1 px-4 py-3 rounded-lg border border-border text-foreground font-medium\n hover:bg-muted transition-colors\"\n >\n Back to Checkout\n </button>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <CreditCard className=\"size-5 text-muted-foreground\" />\n <span className=\"font-medium text-foreground\">Card Payment</span>\n </div>\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <Lock className=\"size-3\" />\n Secured by Stripe\n </div>\n </div>\n\n {/* Stripe Card Element container - NO conditional rendering inside */}\n <div className=\"space-y-2\">\n <div\n ref={cardElementRef}\n className=\"min-h-[50px] rounded-lg border border-border bg-background p-4\"\n />\n {cardError && <p className=\"text-sm text-destructive\">{cardError}</p>}\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"flex items-center gap-2 p-3 rounded-lg bg-destructive/10 text-destructive text-sm\">\n <AlertCircle className=\"size-4 shrink-0\" />\n {error}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n {onCancel && (\n <button\n type=\"button\"\n onClick={onCancel}\n disabled={paymentState === 'processing' || disabled}\n className=\"flex-1 px-4 py-3 rounded-lg border border-border text-foreground font-medium\n hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n Cancel\n </button>\n )}\n <button\n type=\"submit\"\n disabled={paymentState === 'processing' || disabled || !cardComplete}\n className=\"flex-1 px-4 py-3 rounded-lg bg-primary text-primary-foreground font-medium\n hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\n flex items-center justify-center gap-2\"\n >\n {paymentState === 'processing' ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n Processing…\n </>\n ) : (\n <>\n Pay{' '}\n {new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(amount / 100)}\n </>\n )}\n </button>\n </div>\n\n {/* Security note */}\n <p className=\"text-center text-xs text-muted-foreground\">\n Your payment information is encrypted and secure. We never store your full card details.\n </p>\n </form>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"StripePaymentForm.js","names":[],"sources":["../../../../../src/billing/modules/checkout/components/StripePaymentForm.tsx"],"sourcesContent":["/**\n * Stripe Payment Form Component\n * Integrates with Stripe Elements for card payment\n */\n\nimport { type FC, useState, useCallback, useEffect, useRef } from 'react';\nimport { CreditCard, Lock, Loader2, Check, AlertCircle } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { getStripeCardElementStyle, statusTokens } from '../../../shared/utils';\n\n// Stripe types - local definitions to avoid conflicts with external type declarations\ninterface LocalStripeCardElement {\n mount: (element: HTMLElement) => void;\n unmount: () => void;\n destroy: () => void;\n on: (event: string, handler: (event: LocalStripeCardChangeEvent) => void) => void;\n}\n\ninterface LocalStripeCardChangeEvent {\n complete: boolean;\n error?: { message: string };\n}\n\ninterface LocalStripeElements {\n create: (type: 'card', options?: Record<string, unknown>) => LocalStripeCardElement;\n}\n\ninterface LocalStripePaymentMethod {\n id: string;\n card?: {\n last4: string;\n brand: string;\n };\n}\n\ninterface LocalStripeInstance {\n elements: () => LocalStripeElements;\n createPaymentMethod: (options: {\n type: 'card';\n card: LocalStripeCardElement;\n }) => Promise<{ paymentMethod?: LocalStripePaymentMethod; error?: { message: string } }>;\n confirmCardPayment: (\n clientSecret: string,\n options?: { payment_method: string }\n ) => Promise<{\n paymentIntent?: { id: string; status: string };\n error?: { message: string };\n }>;\n}\n\n// Use type assertion when accessing window.Stripe\ntype StripeFactory = (key: string) => LocalStripeInstance;\n\ninterface StripePaymentFormProps {\n clientSecret: string;\n publishableKey: string;\n amount: number;\n currency: string;\n onSuccess: (paymentIntentId: string) => void;\n onError: (error: string) => void;\n onCancel?: () => void;\n disabled?: boolean;\n isCompletingExistingPayment?: boolean; // True for saved cards that need 3D Secure\n}\n\ntype PaymentState = 'idle' | 'loading' | 'processing' | 'success' | 'error';\n\n/**\n * Load Stripe.js SDK dynamically\n */\nconst loadStripeSDK = (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (window.Stripe) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector('script[src=\"https://js.stripe.com/v3/\"]');\n if (existingScript) {\n // Wait for existing script to load\n const checkStripe = setInterval(() => {\n if (window.Stripe) {\n clearInterval(checkStripe);\n resolve();\n }\n }, 100);\n return;\n }\n\n const script = document.createElement('script');\n script.src = 'https://js.stripe.com/v3/';\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('Failed to load Stripe SDK'));\n document.body.appendChild(script);\n });\n};\n\nexport const StripePaymentForm: FC<StripePaymentFormProps> = ({\n clientSecret,\n publishableKey,\n amount,\n currency,\n onSuccess,\n onError,\n onCancel,\n disabled = false,\n isCompletingExistingPayment = false,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const [paymentState, setPaymentState] = useState<PaymentState>('idle');\n const [error, setError] = useState<string | null>(null);\n const [sdkLoaded, setSdkLoaded] = useState(false);\n const [cardComplete, setCardComplete] = useState(false);\n const [cardError, setCardError] = useState<string | null>(null);\n\n const cardElementRef = useRef<HTMLDivElement>(null);\n const stripeRef = useRef<LocalStripeInstance | null>(null);\n const cardElementInstanceRef = useRef<LocalStripeCardElement | null>(null);\n const isMountedRef = useRef(false);\n\n // Load Stripe SDK\n useEffect(() => {\n loadStripeSDK()\n .then(() => {\n setSdkLoaded(true);\n })\n .catch(() => {\n setError('Failed to load payment gateway');\n });\n }, []);\n\n // Initialize Stripe and mount card element (only for new card payments)\n useEffect(() => {\n // Skip card input for completing existing payments (saved cards with 3D Secure)\n if (isCompletingExistingPayment) {\n return;\n }\n\n const windowStripe = (window as unknown as { Stripe?: StripeFactory }).Stripe;\n if (!sdkLoaded || !publishableKey || !windowStripe || isMountedRef.current) {\n return;\n }\n\n // Initialize Stripe\n const stripeInstance = windowStripe(publishableKey);\n stripeRef.current = stripeInstance;\n\n // Create elements\n const elements = stripeInstance.elements();\n const cardElement = elements.create('card', {\n style: getStripeCardElementStyle(),\n });\n cardElementInstanceRef.current = cardElement;\n\n // Mount card element\n if (cardElementRef.current) {\n cardElement.mount(cardElementRef.current);\n isMountedRef.current = true;\n\n // Listen to card element changes\n cardElement.on('change', (event: LocalStripeCardChangeEvent) => {\n setCardError(event.error ? event.error.message : null);\n setCardComplete(event.complete);\n });\n }\n\n // Cleanup\n return () => {\n if (cardElementInstanceRef.current && isMountedRef.current) {\n try {\n cardElementInstanceRef.current.unmount();\n cardElementInstanceRef.current.destroy();\n } catch {\n // Element might already be destroyed\n }\n cardElementInstanceRef.current = null;\n isMountedRef.current = false;\n }\n };\n }, [sdkLoaded, publishableKey, isCompletingExistingPayment]);\n\n // Auto-confirm payment for saved cards (requires 3D Secure or similar action)\n useEffect(() => {\n if (!isCompletingExistingPayment || !sdkLoaded || !publishableKey || paymentState !== 'idle') {\n return;\n }\n\n const confirmExistingPayment = async () => {\n const windowStripe = (window as unknown as { Stripe?: StripeFactory }).Stripe;\n if (!windowStripe) {\n setError('Payment gateway not loaded');\n return;\n }\n\n // Initialize Stripe if not already done\n if (!stripeRef.current) {\n stripeRef.current = windowStripe(publishableKey);\n }\n\n setPaymentState('processing');\n setError(null);\n\n try {\n // Confirm the payment (payment method already attached by backend)\n // This will show 3D Secure popup if needed\n const { paymentIntent, error: confirmError } =\n await stripeRef.current.confirmCardPayment(clientSecret);\n\n if (confirmError) {\n throw new Error(confirmError.message || 'Payment confirmation failed');\n }\n\n if (paymentIntent?.status === 'succeeded') {\n setPaymentState('success');\n onSuccess(paymentIntent.id);\n } else if (paymentIntent?.status === 'processing') {\n setPaymentState('processing');\n // Keep in processing state - webhook will handle completion\n } else {\n throw new Error('Payment was not successful');\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Payment confirmation failed';\n setError(errorMessage);\n setPaymentState('error');\n onError(errorMessage);\n }\n };\n\n confirmExistingPayment();\n }, [\n isCompletingExistingPayment,\n sdkLoaded,\n publishableKey,\n clientSecret,\n paymentState,\n onSuccess,\n onError,\n ]);\n\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n const stripe = stripeRef.current;\n const cardElement = cardElementInstanceRef.current;\n\n if (!stripe || !cardElement) {\n setError('Payment form not ready');\n return;\n }\n\n if (!cardComplete) {\n setCardError('Please enter complete card details');\n return;\n }\n\n setPaymentState('processing');\n setError(null);\n setCardError(null);\n\n try {\n // Step 1: Create PaymentMethod\n const { paymentMethod, error: pmError } = await stripe.createPaymentMethod({\n type: 'card',\n card: cardElement,\n });\n\n if (pmError) {\n throw new Error(pmError.message || 'Failed to create payment method');\n }\n\n if (!paymentMethod) {\n throw new Error('No payment method returned');\n }\n\n // Step 2: Confirm the payment with the client secret\n const { paymentIntent, error: confirmError } = await stripe.confirmCardPayment(\n clientSecret,\n { payment_method: paymentMethod.id }\n );\n\n if (confirmError) {\n throw new Error(confirmError.message || 'Payment failed');\n }\n\n if (paymentIntent?.status === 'succeeded') {\n setPaymentState('success');\n onSuccess(paymentIntent.id);\n } else if (paymentIntent?.status === 'processing') {\n setPaymentState('processing');\n } else {\n throw new Error('Payment was not successful');\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Payment failed';\n setError(errorMessage);\n setPaymentState('error');\n onError(errorMessage);\n }\n },\n [clientSecret, cardComplete, onSuccess, onError]\n );\n\n // Render success state\n if (paymentState === 'success') {\n return (\n <div\n className={`p-6 rounded-lg border ${statusTokens.success.border} ${statusTokens.success.bg}`}\n >\n <div className=\"flex items-center gap-3\">\n <div\n className={`p-2 rounded-full ${statusTokens.success.bg} ${statusTokens.success.icon}`}\n >\n <Check className=\"size-6\" />\n </div>\n <div>\n <h3 className={`font-semibold ${statusTokens.success.text}`}>Payment Successful!</h3>\n <p className={`text-sm ${statusTokens.success.text}`}>\n Your payment has been processed successfully.\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n // Show loading while SDK loads\n if (!sdkLoaded) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2\">\n <CreditCard className=\"size-5 text-text-secondary\" />\n <span className=\"font-medium text-text-primary\">\n {tr('billing.checkout.cardPayment', 'Card Payment')}\n </span>\n </div>\n <div className=\"p-6 rounded-lg border border-border-subtle bg-bg-sunken flex items-center justify-center\">\n <Loader2 className=\"size-6 animate-spin text-text-secondary\" />\n <span className=\"ml-2 text-text-secondary\">\n {tr('billing.checkout.loadingPaymentForm', 'Loading payment form...')}\n </span>\n </div>\n </div>\n );\n }\n\n // For saved card payments that need confirmation (3D Secure, etc.)\n if (isCompletingExistingPayment) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2\">\n <Lock className=\"size-5 text-text-link\" />\n <span className=\"font-medium text-text-primary\">Secure Payment Verification</span>\n </div>\n\n {paymentState === 'processing' && (\n <div className=\"p-6 rounded-lg border border-border-subtle bg-bg-sunken flex flex-col items-center justify-center space-y-3\">\n <Loader2 className=\"size-8 animate-spin text-text-link\" />\n <p className=\"text-sm text-text-secondary text-center\">\n Confirming payment with your saved card…\n <br />\n <span className=\"text-xs\">Please complete any security verification if prompted</span>\n </p>\n </div>\n )}\n\n {error && (\n <div className=\"flex items-center gap-2 p-3 rounded-lg bg-status-error-bg-subtle text-status-error-text text-sm\">\n <AlertCircle className=\"size-4 shrink-0\" />\n <div>\n <p className=\"font-medium\">\n {tr('billing.checkout.paymentFailed', 'Payment Failed')}\n </p>\n <p className=\"text-xs\">{error}</p>\n </div>\n </div>\n )}\n\n {(paymentState === 'error' || error) && onCancel && (\n <div className=\"flex gap-3\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"flex-1 px-4 py-3 rounded-lg border border-border-subtle text-text-primary font-medium\n hover:bg-bg-sunken transition-colors\"\n >\n Back to Checkout\n </button>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <CreditCard className=\"size-5 text-text-secondary\" />\n <span className=\"font-medium text-text-primary\">Card Payment</span>\n </div>\n <div className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Lock className=\"size-3\" />\n Secured by Stripe\n </div>\n </div>\n\n {/* Stripe Card Element container - NO conditional rendering inside */}\n <div className=\"space-y-2\">\n <div\n ref={cardElementRef}\n className=\"min-h-[50px] rounded-lg border border-border-subtle bg-bg-surface p-4\"\n />\n {cardError && <p className=\"text-sm text-status-error-text\">{cardError}</p>}\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"flex items-center gap-2 p-3 rounded-lg bg-status-error-bg-subtle text-status-error-text text-sm\">\n <AlertCircle className=\"size-4 shrink-0\" />\n {error}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n {onCancel && (\n <button\n type=\"button\"\n onClick={onCancel}\n disabled={paymentState === 'processing' || disabled}\n className=\"flex-1 px-4 py-3 rounded-lg border border-border-subtle text-text-primary font-medium\n hover:bg-bg-sunken disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n Cancel\n </button>\n )}\n <button\n type=\"submit\"\n disabled={paymentState === 'processing' || disabled || !cardComplete}\n className=\"flex-1 px-4 py-3 rounded-lg bg-action-primary-bg text-action-primary-text font-medium\n hover:bg-action-primary-bgHover disabled:opacity-50 disabled:cursor-not-allowed transition-colors\n flex items-center justify-center gap-2\"\n >\n {paymentState === 'processing' ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n Processing…\n </>\n ) : (\n <>\n Pay{' '}\n {new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(amount / 100)}\n </>\n )}\n </button>\n </div>\n\n {/* Security note */}\n <p className=\"text-center text-xs text-text-secondary\">\n Your payment information is encrypted and secure. We never store your full card details.\n </p>\n </form>\n );\n};\n"],"mappings":"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"}
@@ -25,8 +25,8 @@ var u = ({ subscriptions: u, selectedSubscriptionId: d, onSelect: f, isLoading:
25
25
  let t = e.plan?.name || "Subscription", n = e.plan?.product?.name;
26
26
  return n ? `${n} - ${t}` : t;
27
27
  };
28
- return p ? /* @__PURE__ */ s("div", { className: "h-9 bg-muted animate-pulse rounded-md" }) : u.length === 0 ? /* @__PURE__ */ c("div", {
29
- className: `flex items-center gap-2 p-2 rounded-md ${e.warning.bg} border ${e.warning.border}`,
28
+ return p ? /* @__PURE__ */ s("div", { className: "h-9 bg-bg-sunken animate-pulse rounded-button" }) : u.length === 0 ? /* @__PURE__ */ c("div", {
29
+ className: `flex items-center gap-2 p-2 rounded-button ${e.warning.bg} border ${e.warning.border}`,
30
30
  children: [/* @__PURE__ */ s(i, { className: `size-4 ${e.warning.icon} shrink-0` }), /* @__PURE__ */ s("span", {
31
31
  className: `text-sm ${e.warning.text}`,
32
32
  children: "No active subscription. Subscribe to a plan first."
@@ -37,26 +37,26 @@ var u = ({ subscriptions: u, selectedSubscriptionId: d, onSelect: f, isLoading:
37
37
  children: [/* @__PURE__ */ c("div", {
38
38
  className: "flex items-center gap-2",
39
39
  children: [/* @__PURE__ */ s("span", {
40
- className: "text-sm text-muted-foreground shrink-0",
40
+ className: "text-sm text-text-secondary shrink-0",
41
41
  children: h("billing.checkout.attachTo", "Attach to:")
42
42
  }), /* @__PURE__ */ c("button", {
43
43
  type: "button",
44
44
  onClick: () => _(!g),
45
45
  className: `
46
- flex-1 flex items-center justify-between gap-2 px-3 py-1.5 rounded-md border text-sm
46
+ flex-1 flex items-center justify-between gap-2 px-3 py-1.5 rounded-button border text-sm
47
47
  transition-colors text-left
48
- ${g ? "border-primary ring-1 ring-primary" : d ? "border-border hover:border-primary/50 bg-background" : `${e.warning.border} ${e.warning.bg}`}
48
+ ${g ? "border-border-strong ring-1 ring-[var(--color-focus-ring)]" : d ? "border-border-subtle hover:border-border-strong bg-bg-surface" : `${e.warning.border} ${e.warning.bg}`}
49
49
  `,
50
50
  children: [y ? /* @__PURE__ */ s("span", {
51
- className: "font-medium text-foreground truncate",
51
+ className: "font-medium text-text-primary truncate",
52
52
  children: b(y)
53
53
  }) : /* @__PURE__ */ s("span", {
54
54
  className: e.warning.text,
55
55
  children: h("billing.checkout.selectSubscription", "Select subscription")
56
- }), /* @__PURE__ */ s(o, { className: `size-3.5 shrink-0 text-muted-foreground transition-transform ${g ? "rotate-180" : ""}` })]
56
+ }), /* @__PURE__ */ s(o, { className: `size-3.5 shrink-0 text-text-secondary transition-transform ${g ? "rotate-180" : ""}` })]
57
57
  })]
58
58
  }), g && /* @__PURE__ */ s("div", {
59
- className: "absolute left-0 right-0 z-50 mt-1 max-h-48 overflow-auto rounded-md border border-border bg-popover shadow-lg",
59
+ className: "absolute left-0 right-0 z-50 mt-1 max-h-48 overflow-auto rounded-card border border-border-subtle bg-bg-elevated shadow-elevation-3",
60
60
  children: u.map((e) => {
61
61
  let t = e.id === d;
62
62
  return /* @__PURE__ */ c("button", {
@@ -67,12 +67,12 @@ var u = ({ subscriptions: u, selectedSubscriptionId: d, onSelect: f, isLoading:
67
67
  className: `
68
68
  w-full flex items-center justify-between gap-2 px-3 py-2 text-sm text-left
69
69
  transition-colors
70
- ${t ? "bg-primary/5" : "hover:bg-muted/50"}
70
+ ${t ? "bg-[var(--color-accent-soft)]" : "hover:bg-bg-sunken"}
71
71
  `,
72
72
  children: [/* @__PURE__ */ s("span", {
73
- className: "font-medium text-foreground truncate",
73
+ className: "font-medium text-text-primary truncate",
74
74
  children: b(e)
75
- }), t && /* @__PURE__ */ s(a, { className: "size-3.5 text-primary shrink-0" })]
75
+ }), t && /* @__PURE__ */ s(a, { className: "size-3.5 text-text-link shrink-0" })]
76
76
  }, e.id);
77
77
  })
78
78
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionSelector.js","names":[],"sources":["../../../../../src/billing/modules/checkout/components/SubscriptionSelector.tsx"],"sourcesContent":["/**\n * Subscription Selector Component\n * Compact inline dropdown for choosing subscription when purchasing addons\n * Only shows when multiple subscriptions exist - single subscription auto-selects silently\n */\n\nimport { type FC, useState, useRef, useEffect } from 'react';\nimport { ChevronDown, Check, AlertCircle } from 'lucide-react';\nimport { statusTokens } from '../../../shared/utils/tokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface Subscription {\n id: string;\n status: string;\n startDate: string;\n endDate: string;\n plan?: {\n id: string;\n name: string;\n productID?: string;\n product?: {\n id: string;\n name: string;\n } | null;\n } | null;\n}\n\ninterface SubscriptionSelectorProps {\n subscriptions: Subscription[];\n selectedSubscriptionId: string | null;\n onSelect: (subscriptionId: string | null) => void;\n isLoading?: boolean;\n}\n\nexport const SubscriptionSelector: FC<SubscriptionSelectorProps> = ({\n subscriptions,\n selectedSubscriptionId,\n onSelect,\n isLoading = false,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n // Auto-select if only one subscription (silently, no UI shown)\n useEffect(() => {\n if (subscriptions.length === 1 && !selectedSubscriptionId) {\n onSelect(subscriptions[0].id);\n }\n }, [subscriptions, selectedSubscriptionId, onSelect]);\n\n const selectedSubscription = subscriptions.find((s) => s.id === selectedSubscriptionId);\n\n // Format subscription display name: \"Product - Plan\" or just \"Plan\"\n const getDisplayName = (subscription: Subscription) => {\n const planName = subscription.plan?.name || 'Subscription';\n const productName = subscription.plan?.product?.name;\n return productName ? `${productName} - ${planName}` : planName;\n };\n\n // Loading state - compact\n if (isLoading) {\n return <div className=\"h-9 bg-muted animate-pulse rounded-md\" />;\n }\n\n // No subscriptions - compact warning\n if (subscriptions.length === 0) {\n return (\n <div\n className={`flex items-center gap-2 p-2 rounded-md ${statusTokens.warning.bg} border ${statusTokens.warning.border}`}\n >\n <AlertCircle className={`size-4 ${statusTokens.warning.icon} shrink-0`} />\n <span className={`text-sm ${statusTokens.warning.text}`}>\n No active subscription. Subscribe to a plan first.\n </span>\n </div>\n );\n }\n\n // Only one subscription - don't show anything, auto-select happens silently\n if (subscriptions.length === 1) {\n return null;\n }\n\n // Multiple subscriptions - compact dropdown\n return (\n <div className=\"relative\" ref={dropdownRef}>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-muted-foreground shrink-0\">\n {tr('billing.checkout.attachTo', 'Attach to:')}\n </span>\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n flex-1 flex items-center justify-between gap-2 px-3 py-1.5 rounded-md border text-sm\n transition-colors text-left\n ${\n isOpen\n ? 'border-primary ring-1 ring-primary'\n : selectedSubscriptionId\n ? 'border-border hover:border-primary/50 bg-background'\n : `${statusTokens.warning.border} ${statusTokens.warning.bg}`\n }\n `}\n >\n {selectedSubscription ? (\n <span className=\"font-medium text-foreground truncate\">\n {getDisplayName(selectedSubscription)}\n </span>\n ) : (\n <span className={statusTokens.warning.text}>\n {tr('billing.checkout.selectSubscription', 'Select subscription')}\n </span>\n )}\n <ChevronDown\n className={`size-3.5 shrink-0 text-muted-foreground transition-transform ${\n isOpen ? 'rotate-180' : ''\n }`}\n />\n </button>\n </div>\n\n {/* Dropdown menu */}\n {isOpen && (\n <div className=\"absolute left-0 right-0 z-50 mt-1 max-h-48 overflow-auto rounded-md border border-border bg-popover shadow-lg\">\n {subscriptions.map((subscription) => {\n const isSelected = subscription.id === selectedSubscriptionId;\n return (\n <button\n key={subscription.id}\n type=\"button\"\n onClick={() => {\n onSelect(subscription.id);\n setIsOpen(false);\n }}\n className={`\n w-full flex items-center justify-between gap-2 px-3 py-2 text-sm text-left\n transition-colors\n ${isSelected ? 'bg-primary/5' : 'hover:bg-muted/50'}\n `}\n >\n <span className=\"font-medium text-foreground truncate\">\n {getDisplayName(subscription)}\n </span>\n {isSelected && <Check className=\"size-3.5 text-primary shrink-0\" />}\n </button>\n );\n })}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;AAkCA,IAAa,KAAuD,EAClE,kBACA,2BACA,aACA,eAAY,SACR;CACJ,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAa,EAAE,EAAI;AACzB,SAAO,MAAe,IAAM,IAAW;IAEnC,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,IAAc,EAAuB,KAAK;AAehD,CAZA,QAAgB;EACd,IAAM,KAAsB,MAAsB;AAChD,GAAI,EAAY,WAAW,CAAC,EAAY,QAAQ,SAAS,EAAM,OAAe,IAC5E,EAAU,GAAM;;AAKpB,SADA,SAAS,iBAAiB,aAAa,EAAmB,QAC7C,SAAS,oBAAoB,aAAa,EAAmB;IACzE,EAAE,CAAC,EAGN,QAAgB;AACd,EAAI,EAAc,WAAW,KAAK,CAAC,KACjC,EAAS,EAAc,GAAG,GAAG;IAE9B;EAAC;EAAe;EAAwB;EAAS,CAAC;CAErD,IAAM,IAAuB,EAAc,MAAM,MAAM,EAAE,OAAO,EAAuB,EAGjF,KAAkB,MAA+B;EACrD,IAAM,IAAW,EAAa,MAAM,QAAQ,gBACtC,IAAc,EAAa,MAAM,SAAS;AAChD,SAAO,IAAc,GAAG,EAAY,KAAK,MAAa;;AA4BxD,QAxBI,IACK,kBAAC,OAAD,EAAK,WAAU,yCAA0C,CAAA,GAI9D,EAAc,WAAW,IAEzB,kBAAC,OAAD;EACE,WAAW,0CAA0C,EAAa,QAAQ,GAAG,UAAU,EAAa,QAAQ;YAD9G,CAGE,kBAAC,GAAD,EAAa,WAAW,UAAU,EAAa,QAAQ,KAAK,YAAc,CAAA,EAC1E,kBAAC,QAAD;GAAM,WAAW,WAAW,EAAa,QAAQ;aAAQ;GAElD,CAAA,CACH;MAKN,EAAc,WAAW,IACpB,OAKP,kBAAC,OAAD;EAAK,WAAU;EAAW,KAAK;YAA/B,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,QAAD;IAAM,WAAU;cACb,EAAG,6BAA6B,aAAa;IACzC,CAAA,EACP,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAU,CAAC,EAAO;IACjC,WAAW;;;cAIP,IACI,uCACA,IACE,wDACA,GAAG,EAAa,QAAQ,OAAO,GAAG,EAAa,QAAQ,KAC9D;;cAZL,CAeG,IACC,kBAAC,QAAD;KAAM,WAAU;eACb,EAAe,EAAqB;KAChC,CAAA,GAEP,kBAAC,QAAD;KAAM,WAAW,EAAa,QAAQ;eACnC,EAAG,uCAAuC,sBAAsB;KAC5D,CAAA,EAET,kBAAC,GAAD,EACE,WAAW,gEACT,IAAS,eAAe,MAE1B,CAAA,CACK;MACL;MAGL,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAc,KAAK,MAAiB;IACnC,IAAM,IAAa,EAAa,OAAO;AACvC,WACE,kBAAC,UAAD;KAEE,MAAK;KACL,eAAe;AAEb,MADA,EAAS,EAAa,GAAG,EACzB,EAAU,GAAM;;KAElB,WAAW;;;oBAGP,IAAa,iBAAiB,oBAAoB;;eAVxD,CAaE,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAe,EAAa;MACxB,CAAA,EACN,KAAc,kBAAC,GAAD,EAAO,WAAU,kCAAmC,CAAA,CAC5D;OAhBF,EAAa,GAgBX;KAEX;GACE,CAAA,CAEJ"}
1
+ {"version":3,"file":"SubscriptionSelector.js","names":[],"sources":["../../../../../src/billing/modules/checkout/components/SubscriptionSelector.tsx"],"sourcesContent":["/**\n * Subscription Selector Component\n * Compact inline dropdown for choosing subscription when purchasing addons\n * Only shows when multiple subscriptions exist - single subscription auto-selects silently\n */\n\nimport { type FC, useState, useRef, useEffect } from 'react';\nimport { ChevronDown, Check, AlertCircle } from 'lucide-react';\nimport { statusTokens } from '../../../shared/utils/tokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface Subscription {\n id: string;\n status: string;\n startDate: string;\n endDate: string;\n plan?: {\n id: string;\n name: string;\n productID?: string;\n product?: {\n id: string;\n name: string;\n } | null;\n } | null;\n}\n\ninterface SubscriptionSelectorProps {\n subscriptions: Subscription[];\n selectedSubscriptionId: string | null;\n onSelect: (subscriptionId: string | null) => void;\n isLoading?: boolean;\n}\n\nexport const SubscriptionSelector: FC<SubscriptionSelectorProps> = ({\n subscriptions,\n selectedSubscriptionId,\n onSelect,\n isLoading = false,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n // Auto-select if only one subscription (silently, no UI shown)\n useEffect(() => {\n if (subscriptions.length === 1 && !selectedSubscriptionId) {\n onSelect(subscriptions[0].id);\n }\n }, [subscriptions, selectedSubscriptionId, onSelect]);\n\n const selectedSubscription = subscriptions.find((s) => s.id === selectedSubscriptionId);\n\n // Format subscription display name: \"Product - Plan\" or just \"Plan\"\n const getDisplayName = (subscription: Subscription) => {\n const planName = subscription.plan?.name || 'Subscription';\n const productName = subscription.plan?.product?.name;\n return productName ? `${productName} - ${planName}` : planName;\n };\n\n // Loading state - compact\n if (isLoading) {\n return <div className=\"h-9 bg-bg-sunken animate-pulse rounded-button\" />;\n }\n\n // No subscriptions - compact warning\n if (subscriptions.length === 0) {\n return (\n <div\n className={`flex items-center gap-2 p-2 rounded-button ${statusTokens.warning.bg} border ${statusTokens.warning.border}`}\n >\n <AlertCircle className={`size-4 ${statusTokens.warning.icon} shrink-0`} />\n <span className={`text-sm ${statusTokens.warning.text}`}>\n No active subscription. Subscribe to a plan first.\n </span>\n </div>\n );\n }\n\n // Only one subscription - don't show anything, auto-select happens silently\n if (subscriptions.length === 1) {\n return null;\n }\n\n // Multiple subscriptions - compact dropdown\n return (\n <div className=\"relative\" ref={dropdownRef}>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary shrink-0\">\n {tr('billing.checkout.attachTo', 'Attach to:')}\n </span>\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n flex-1 flex items-center justify-between gap-2 px-3 py-1.5 rounded-button border text-sm\n transition-colors text-left\n ${\n isOpen\n ? 'border-border-strong ring-1 ring-[var(--color-focus-ring)]'\n : selectedSubscriptionId\n ? 'border-border-subtle hover:border-border-strong bg-bg-surface'\n : `${statusTokens.warning.border} ${statusTokens.warning.bg}`\n }\n `}\n >\n {selectedSubscription ? (\n <span className=\"font-medium text-text-primary truncate\">\n {getDisplayName(selectedSubscription)}\n </span>\n ) : (\n <span className={statusTokens.warning.text}>\n {tr('billing.checkout.selectSubscription', 'Select subscription')}\n </span>\n )}\n <ChevronDown\n className={`size-3.5 shrink-0 text-text-secondary transition-transform ${\n isOpen ? 'rotate-180' : ''\n }`}\n />\n </button>\n </div>\n\n {/* Dropdown menu */}\n {isOpen && (\n <div className=\"absolute left-0 right-0 z-50 mt-1 max-h-48 overflow-auto rounded-card border border-border-subtle bg-bg-elevated shadow-elevation-3\">\n {subscriptions.map((subscription) => {\n const isSelected = subscription.id === selectedSubscriptionId;\n return (\n <button\n key={subscription.id}\n type=\"button\"\n onClick={() => {\n onSelect(subscription.id);\n setIsOpen(false);\n }}\n className={`\n w-full flex items-center justify-between gap-2 px-3 py-2 text-sm text-left\n transition-colors\n ${isSelected ? 'bg-[var(--color-accent-soft)]' : 'hover:bg-bg-sunken'}\n `}\n >\n <span className=\"font-medium text-text-primary truncate\">\n {getDisplayName(subscription)}\n </span>\n {isSelected && <Check className=\"size-3.5 text-text-link shrink-0\" />}\n </button>\n );\n })}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;AAkCA,IAAa,KAAuD,EAClE,kBACA,2BACA,aACA,eAAY,SACR;CACJ,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAa,EAAE,EAAI;AACzB,SAAO,MAAe,IAAM,IAAW;IAEnC,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,IAAc,EAAuB,KAAK;AAehD,CAZA,QAAgB;EACd,IAAM,KAAsB,MAAsB;AAChD,GAAI,EAAY,WAAW,CAAC,EAAY,QAAQ,SAAS,EAAM,OAAe,IAC5E,EAAU,GAAM;;AAKpB,SADA,SAAS,iBAAiB,aAAa,EAAmB,QAC7C,SAAS,oBAAoB,aAAa,EAAmB;IACzE,EAAE,CAAC,EAGN,QAAgB;AACd,EAAI,EAAc,WAAW,KAAK,CAAC,KACjC,EAAS,EAAc,GAAG,GAAG;IAE9B;EAAC;EAAe;EAAwB;EAAS,CAAC;CAErD,IAAM,IAAuB,EAAc,MAAM,MAAM,EAAE,OAAO,EAAuB,EAGjF,KAAkB,MAA+B;EACrD,IAAM,IAAW,EAAa,MAAM,QAAQ,gBACtC,IAAc,EAAa,MAAM,SAAS;AAChD,SAAO,IAAc,GAAG,EAAY,KAAK,MAAa;;AA4BxD,QAxBI,IACK,kBAAC,OAAD,EAAK,WAAU,iDAAkD,CAAA,GAItE,EAAc,WAAW,IAEzB,kBAAC,OAAD;EACE,WAAW,8CAA8C,EAAa,QAAQ,GAAG,UAAU,EAAa,QAAQ;YADlH,CAGE,kBAAC,GAAD,EAAa,WAAW,UAAU,EAAa,QAAQ,KAAK,YAAc,CAAA,EAC1E,kBAAC,QAAD;GAAM,WAAW,WAAW,EAAa,QAAQ;aAAQ;GAElD,CAAA,CACH;MAKN,EAAc,WAAW,IACpB,OAKP,kBAAC,OAAD;EAAK,WAAU;EAAW,KAAK;YAA/B,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,QAAD;IAAM,WAAU;cACb,EAAG,6BAA6B,aAAa;IACzC,CAAA,EACP,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAU,CAAC,EAAO;IACjC,WAAW;;;cAIP,IACI,+DACA,IACE,kEACA,GAAG,EAAa,QAAQ,OAAO,GAAG,EAAa,QAAQ,KAC9D;;cAZL,CAeG,IACC,kBAAC,QAAD;KAAM,WAAU;eACb,EAAe,EAAqB;KAChC,CAAA,GAEP,kBAAC,QAAD;KAAM,WAAW,EAAa,QAAQ;eACnC,EAAG,uCAAuC,sBAAsB;KAC5D,CAAA,EAET,kBAAC,GAAD,EACE,WAAW,8DACT,IAAS,eAAe,MAE1B,CAAA,CACK;MACL;MAGL,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAc,KAAK,MAAiB;IACnC,IAAM,IAAa,EAAa,OAAO;AACvC,WACE,kBAAC,UAAD;KAEE,MAAK;KACL,eAAe;AAEb,MADA,EAAS,EAAa,GAAG,EACzB,EAAU,GAAM;;KAElB,WAAW;;;oBAGP,IAAa,kCAAkC,qBAAqB;;eAV1E,CAaE,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAe,EAAa;MACxB,CAAA,EACN,KAAc,kBAAC,GAAD,EAAO,WAAU,oCAAqC,CAAA,CAC9D;OAhBF,EAAa,GAgBX;KAEX;GACE,CAAA,CAEJ"}
@@ -16,11 +16,11 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
16
16
  return /* @__PURE__ */ s("div", {
17
17
  className: "space-y-3",
18
18
  children: [/* @__PURE__ */ o("h3", {
19
- className: "text-sm font-medium text-foreground",
19
+ className: "text-sm font-medium text-text-primary",
20
20
  children: E("billing.checkout.paymentMethod", "Payment Method")
21
21
  }), w ? /* @__PURE__ */ s("div", {
22
22
  className: "space-y-2",
23
- children: [/* @__PURE__ */ o("div", { className: "h-16 rounded-lg border border-border bg-muted animate-pulse" }), /* @__PURE__ */ o("div", { className: "h-16 rounded-lg border border-border bg-muted animate-pulse" })]
23
+ children: [/* @__PURE__ */ o("div", { className: "h-16 rounded-lg border border-border-subtle bg-bg-sunken animate-pulse" }), /* @__PURE__ */ o("div", { className: "h-16 rounded-lg border border-border-subtle bg-bg-sunken animate-pulse" })]
24
24
  }) : /* @__PURE__ */ s("div", {
25
25
  className: "space-y-2",
26
26
  children: [
@@ -30,18 +30,18 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
30
30
  disabled: !k,
31
31
  className: `
32
32
  w-full flex items-center gap-3 p-4 rounded-lg border transition-all text-left
33
- ${P("new", "CREDITS") ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:border-primary/50 hover:bg-muted/50"}
33
+ ${P("new", "CREDITS") ? "border-border-strong bg-[var(--color-accent-soft)] ring-1 ring-[var(--color-focus-ring)]" : "border-border-subtle hover:border-border-strong hover:bg-bg-sunken"}
34
34
  ${!k && "opacity-50 cursor-not-allowed"}
35
35
  `,
36
36
  children: [
37
- /* @__PURE__ */ o(n, { className: `size-5 shrink-0 ${P("new", "CREDITS") ? "text-primary" : "text-muted-foreground"}` }),
37
+ /* @__PURE__ */ o(n, { className: `size-5 shrink-0 ${P("new", "CREDITS") ? "text-text-link" : "text-text-secondary"}` }),
38
38
  /* @__PURE__ */ s("div", {
39
39
  className: "flex-1 min-w-0",
40
40
  children: [/* @__PURE__ */ o("div", {
41
- className: "text-sm font-medium text-foreground",
41
+ className: "text-sm font-medium text-text-primary",
42
42
  children: "Pay with Credits"
43
43
  }), /* @__PURE__ */ o("div", {
44
- className: "text-xs text-muted-foreground",
44
+ className: "text-xs text-text-secondary",
45
45
  children: k ? `Available: ${v.toLocaleString()} credits` : `Insufficient credits (need ${y.toLocaleString()})`
46
46
  })]
47
47
  }),
@@ -53,7 +53,7 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
53
53
  }),
54
54
  i.length > 0 && /* @__PURE__ */ s(a, { children: [
55
55
  /* @__PURE__ */ o("div", {
56
- className: "text-xs font-medium text-muted-foreground uppercase tracking-wide pt-2",
56
+ className: "text-xs font-medium text-text-secondary uppercase tracking-wide pt-2",
57
57
  children: "Saved Cards"
58
58
  }),
59
59
  j && /* @__PURE__ */ s("button", {
@@ -61,17 +61,17 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
61
61
  onClick: () => N("saved", j.id),
62
62
  className: `
63
63
  w-full flex items-center gap-3 p-4 rounded-lg border transition-all text-left
64
- ${P("saved", j.id) ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:border-primary/50 hover:bg-muted/50"}
64
+ ${P("saved", j.id) ? "border-border-strong bg-[var(--color-accent-soft)] ring-1 ring-[var(--color-focus-ring)]" : "border-border-subtle hover:border-border-strong hover:bg-bg-sunken"}
65
65
  `,
66
66
  children: [
67
67
  l(j.type),
68
68
  /* @__PURE__ */ s("div", {
69
69
  className: "flex-1 min-w-0",
70
70
  children: [/* @__PURE__ */ o("div", {
71
- className: "text-sm font-medium text-foreground",
71
+ className: "text-sm font-medium text-text-primary",
72
72
  children: u(j)
73
73
  }), j.expiryMonth && j.expiryYear && /* @__PURE__ */ s("div", {
74
- className: "text-xs text-muted-foreground",
74
+ className: "text-xs text-text-secondary",
75
75
  children: [
76
76
  "Expires ",
77
77
  j.expiryMonth.toString().padStart(2, "0"),
@@ -81,7 +81,7 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
81
81
  })]
82
82
  }),
83
83
  j.isDefault && /* @__PURE__ */ o("span", {
84
- className: "text-xs px-2 py-0.5 rounded bg-primary/10 text-primary",
84
+ className: "text-xs px-2 py-0.5 rounded bg-[var(--color-accent-soft)] text-text-link",
85
85
  children: "Default"
86
86
  })
87
87
  ]
@@ -91,15 +91,15 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
91
91
  onClick: () => N("saved", e.id),
92
92
  className: `
93
93
  w-full flex items-center gap-3 p-4 rounded-lg border transition-all text-left
94
- ${P("saved", e.id) ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:border-primary/50 hover:bg-muted/50"}
94
+ ${P("saved", e.id) ? "border-border-strong bg-[var(--color-accent-soft)] ring-1 ring-[var(--color-focus-ring)]" : "border-border-subtle hover:border-border-strong hover:bg-bg-sunken"}
95
95
  `,
96
96
  children: [l(e.type), /* @__PURE__ */ s("div", {
97
97
  className: "flex-1 min-w-0",
98
98
  children: [/* @__PURE__ */ o("div", {
99
- className: "text-sm font-medium text-foreground",
99
+ className: "text-sm font-medium text-text-primary",
100
100
  children: u(e)
101
101
  }), e.expiryMonth && e.expiryYear && /* @__PURE__ */ s("div", {
102
- className: "text-xs text-muted-foreground",
102
+ className: "text-xs text-text-secondary",
103
103
  children: [
104
104
  "Expires ",
105
105
  e.expiryMonth.toString().padStart(2, "0"),
@@ -111,12 +111,12 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
111
111
  }, e.id)), /* @__PURE__ */ s("button", {
112
112
  type: "button",
113
113
  onClick: () => O(!1),
114
- className: "text-xs text-primary hover:underline flex items-center gap-1 pl-1",
114
+ className: "text-xs text-text-link hover:underline flex items-center gap-1 pl-1",
115
115
  children: [/* @__PURE__ */ o(t, { className: "size-3 rotate-180" }), "Hide other cards"]
116
116
  })] }) : /* @__PURE__ */ s("button", {
117
117
  type: "button",
118
118
  onClick: () => O(!0),
119
- className: "text-xs text-primary hover:underline flex items-center gap-1 pl-1",
119
+ className: "text-xs text-text-link hover:underline flex items-center gap-1 pl-1",
120
120
  children: [
121
121
  /* @__PURE__ */ o(t, { className: "size-3" }),
122
122
  "Show ",
@@ -127,7 +127,7 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
127
127
  }) })
128
128
  ] }),
129
129
  /* @__PURE__ */ o("div", {
130
- className: "text-xs font-medium text-muted-foreground uppercase tracking-wide pt-2",
130
+ className: "text-xs font-medium text-text-secondary uppercase tracking-wide pt-2",
131
131
  children: i.length > 0 ? "Or use new card" : _ ? "Or pay with card" : "Pay with Card"
132
132
  }),
133
133
  g && A && /* @__PURE__ */ s("button", {
@@ -135,17 +135,17 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
135
135
  onClick: () => N("new", "RAZORPAY"),
136
136
  className: `
137
137
  w-full flex items-center gap-3 p-4 rounded-lg border transition-all text-left
138
- ${P("new", "RAZORPAY") ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:border-primary/50 hover:bg-muted/50"}
138
+ ${P("new", "RAZORPAY") ? "border-border-strong bg-[var(--color-accent-soft)] ring-1 ring-[var(--color-focus-ring)]" : "border-border-subtle hover:border-border-strong hover:bg-bg-sunken"}
139
139
  `,
140
140
  children: [
141
- /* @__PURE__ */ o(r, { className: `size-5 shrink-0 ${P("new", "RAZORPAY") ? "text-primary" : "text-muted-foreground"}` }),
141
+ /* @__PURE__ */ o(r, { className: `size-5 shrink-0 ${P("new", "RAZORPAY") ? "text-text-link" : "text-text-secondary"}` }),
142
142
  /* @__PURE__ */ s("div", {
143
143
  className: "flex-1 min-w-0",
144
144
  children: [/* @__PURE__ */ o("div", {
145
- className: "text-sm font-medium text-foreground",
145
+ className: "text-sm font-medium text-text-primary",
146
146
  children: "UPI / Cards / Netbanking"
147
147
  }), /* @__PURE__ */ o("div", {
148
- className: "text-xs text-muted-foreground",
148
+ className: "text-xs text-text-secondary",
149
149
  children: "Razorpay"
150
150
  })]
151
151
  }),
@@ -160,17 +160,17 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
160
160
  onClick: () => N("new", "STRIPE"),
161
161
  className: `
162
162
  w-full flex items-center gap-3 p-4 rounded-lg border transition-all text-left
163
- ${P("new", "STRIPE") ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:border-primary/50 hover:bg-muted/50"}
163
+ ${P("new", "STRIPE") ? "border-border-strong bg-[var(--color-accent-soft)] ring-1 ring-[var(--color-focus-ring)]" : "border-border-subtle hover:border-border-strong hover:bg-bg-sunken"}
164
164
  `,
165
165
  children: [
166
- /* @__PURE__ */ o(r, { className: `size-5 shrink-0 ${P("new", "STRIPE") ? "text-primary" : "text-muted-foreground"}` }),
166
+ /* @__PURE__ */ o(r, { className: `size-5 shrink-0 ${P("new", "STRIPE") ? "text-text-link" : "text-text-secondary"}` }),
167
167
  /* @__PURE__ */ s("div", {
168
168
  className: "flex-1 min-w-0",
169
169
  children: [/* @__PURE__ */ o("div", {
170
- className: "text-sm font-medium text-foreground",
170
+ className: "text-sm font-medium text-text-primary",
171
171
  children: "Credit / Debit Cards"
172
172
  }), /* @__PURE__ */ o("div", {
173
- className: "text-xs text-muted-foreground",
173
+ className: "text-xs text-text-secondary",
174
174
  children: "Stripe - Multi-currency"
175
175
  })]
176
176
  }),
@@ -181,30 +181,30 @@ var l = (e) => o(e === "WALLET" ? i : r, { className: "size-4" }), u = (e) => `$
181
181
  ]
182
182
  }),
183
183
  !d && p !== "CREDITS" && p !== "AUTO" && !C && /* @__PURE__ */ o("div", {
184
- className: "mt-4 pt-4 border-t border-border",
184
+ className: "mt-4 pt-4 border-t border-border-subtle",
185
185
  children: /* @__PURE__ */ s("label", {
186
186
  className: "flex items-start gap-3 cursor-pointer group",
187
187
  children: [/* @__PURE__ */ o("input", {
188
188
  type: "checkbox",
189
189
  checked: x,
190
190
  onChange: (e) => S(e.target.checked),
191
- className: "mt-0.5 size-4 rounded border-border text-primary focus:ring-primary focus:ring-offset-0"
191
+ className: "mt-0.5 size-4 rounded border-border-subtle text-text-link focus:ring-[var(--color-focus-ring)] focus:ring-offset-0"
192
192
  }), /* @__PURE__ */ s("div", {
193
193
  className: "flex-1",
194
194
  children: [/* @__PURE__ */ o("div", {
195
- className: "text-sm font-medium text-foreground group-hover:text-primary transition-colors",
195
+ className: "text-sm font-medium text-text-primary group-hover:text-text-link transition-colors",
196
196
  children: "Save card for future use"
197
197
  }), /* @__PURE__ */ o("div", {
198
- className: "text-xs text-muted-foreground mt-0.5",
198
+ className: "text-xs text-text-secondary mt-0.5",
199
199
  children: "Securely save this payment method for faster checkout next time"
200
200
  })]
201
201
  })]
202
202
  })
203
203
  }),
204
204
  !d && p !== "CREDITS" && p !== "AUTO" && C && /* @__PURE__ */ o("div", {
205
- className: "mt-4 pt-4 border-t border-border",
205
+ className: "mt-4 pt-4 border-t border-border-subtle",
206
206
  children: /* @__PURE__ */ s("div", {
207
- className: "flex items-start gap-2 text-xs text-muted-foreground bg-muted/50 p-3 rounded-lg",
207
+ className: "flex items-start gap-2 text-xs text-text-secondary bg-bg-sunken p-3 rounded-lg",
208
208
  children: [/* @__PURE__ */ o("svg", {
209
209
  className: "size-4 mt-0.5 flex-shrink-0",
210
210
  fill: "none",