@mmailaender/convex-creem 0.1.0

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 (383) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1176 -0
  3. package/dist/client/helpers.d.ts +17 -0
  4. package/dist/client/helpers.d.ts.map +1 -0
  5. package/dist/client/helpers.js +43 -0
  6. package/dist/client/helpers.js.map +1 -0
  7. package/dist/client/index.d.ts +1041 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +1068 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/client/parsers.d.ts +45 -0
  12. package/dist/client/parsers.d.ts.map +1 -0
  13. package/dist/client/parsers.js +138 -0
  14. package/dist/client/parsers.js.map +1 -0
  15. package/dist/client/polyfill.d.ts +2 -0
  16. package/dist/client/polyfill.d.ts.map +1 -0
  17. package/dist/client/polyfill.js +3 -0
  18. package/dist/client/polyfill.js.map +1 -0
  19. package/dist/component/_generated/api.d.ts +36 -0
  20. package/dist/component/_generated/api.d.ts.map +1 -0
  21. package/dist/component/_generated/api.js +31 -0
  22. package/dist/component/_generated/api.js.map +1 -0
  23. package/dist/component/_generated/component.d.ts +542 -0
  24. package/dist/component/_generated/component.d.ts.map +1 -0
  25. package/dist/component/_generated/component.js +11 -0
  26. package/dist/component/_generated/component.js.map +1 -0
  27. package/dist/component/_generated/dataModel.d.ts +46 -0
  28. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  29. package/dist/component/_generated/dataModel.js +11 -0
  30. package/dist/component/_generated/dataModel.js.map +1 -0
  31. package/dist/component/_generated/server.d.ts +121 -0
  32. package/dist/component/_generated/server.d.ts.map +1 -0
  33. package/dist/component/_generated/server.js +78 -0
  34. package/dist/component/_generated/server.js.map +1 -0
  35. package/dist/component/convex.config.d.ts +3 -0
  36. package/dist/component/convex.config.d.ts.map +1 -0
  37. package/dist/component/convex.config.js +3 -0
  38. package/dist/component/convex.config.js.map +1 -0
  39. package/dist/component/lib.d.ts +1005 -0
  40. package/dist/component/lib.d.ts.map +1 -0
  41. package/dist/component/lib.js +647 -0
  42. package/dist/component/lib.js.map +1 -0
  43. package/dist/component/schema.d.ts +191 -0
  44. package/dist/component/schema.d.ts.map +1 -0
  45. package/dist/component/schema.js +104 -0
  46. package/dist/component/schema.js.map +1 -0
  47. package/dist/component/util.d.ts +61 -0
  48. package/dist/component/util.d.ts.map +1 -0
  49. package/dist/component/util.js +142 -0
  50. package/dist/component/util.js.map +1 -0
  51. package/dist/core/catalog.d.ts +18 -0
  52. package/dist/core/catalog.d.ts.map +1 -0
  53. package/dist/core/catalog.js +82 -0
  54. package/dist/core/catalog.js.map +1 -0
  55. package/dist/core/index.d.ts +9 -0
  56. package/dist/core/index.d.ts.map +1 -0
  57. package/dist/core/index.js +9 -0
  58. package/dist/core/index.js.map +1 -0
  59. package/dist/core/markdown.d.ts +12 -0
  60. package/dist/core/markdown.d.ts.map +1 -0
  61. package/dist/core/markdown.js +26 -0
  62. package/dist/core/markdown.js.map +1 -0
  63. package/dist/core/payments.d.ts +11 -0
  64. package/dist/core/payments.d.ts.map +1 -0
  65. package/dist/core/payments.js +27 -0
  66. package/dist/core/payments.js.map +1 -0
  67. package/dist/core/pendingCheckout.d.ts +15 -0
  68. package/dist/core/pendingCheckout.d.ts.map +1 -0
  69. package/dist/core/pendingCheckout.js +40 -0
  70. package/dist/core/pendingCheckout.js.map +1 -0
  71. package/dist/core/resolver.d.ts +11 -0
  72. package/dist/core/resolver.d.ts.map +1 -0
  73. package/dist/core/resolver.js +106 -0
  74. package/dist/core/resolver.js.map +1 -0
  75. package/dist/core/selectors.d.ts +12 -0
  76. package/dist/core/selectors.d.ts.map +1 -0
  77. package/dist/core/selectors.js +18 -0
  78. package/dist/core/selectors.js.map +1 -0
  79. package/dist/core/subscriptionUpdate.d.ts +20 -0
  80. package/dist/core/subscriptionUpdate.d.ts.map +1 -0
  81. package/dist/core/subscriptionUpdate.js +64 -0
  82. package/dist/core/subscriptionUpdate.js.map +1 -0
  83. package/dist/core/types.d.ts +170 -0
  84. package/dist/core/types.d.ts.map +1 -0
  85. package/dist/core/types.js +15 -0
  86. package/dist/core/types.js.map +1 -0
  87. package/dist/design-system/colors/color-utils.d.ts +10 -0
  88. package/dist/design-system/colors/color-utils.d.ts.map +1 -0
  89. package/dist/design-system/colors/color-utils.js +91 -0
  90. package/dist/design-system/colors/color-utils.js.map +1 -0
  91. package/dist/design-system/colors/config.d.ts +33 -0
  92. package/dist/design-system/colors/config.d.ts.map +1 -0
  93. package/dist/design-system/colors/config.js +224 -0
  94. package/dist/design-system/colors/config.js.map +1 -0
  95. package/dist/design-system/colors/index.d.ts +3 -0
  96. package/dist/design-system/colors/index.d.ts.map +1 -0
  97. package/dist/design-system/colors/index.js +3 -0
  98. package/dist/design-system/colors/index.js.map +1 -0
  99. package/dist/design-system/rounded/config.d.ts +31 -0
  100. package/dist/design-system/rounded/config.d.ts.map +1 -0
  101. package/dist/design-system/rounded/config.js +76 -0
  102. package/dist/design-system/rounded/config.js.map +1 -0
  103. package/dist/design-system/rounded/index.d.ts +2 -0
  104. package/dist/design-system/rounded/index.d.ts.map +1 -0
  105. package/dist/design-system/rounded/index.js +2 -0
  106. package/dist/design-system/rounded/index.js.map +1 -0
  107. package/dist/design-system/typography/config.d.ts +55 -0
  108. package/dist/design-system/typography/config.d.ts.map +1 -0
  109. package/dist/design-system/typography/config.js +308 -0
  110. package/dist/design-system/typography/config.js.map +1 -0
  111. package/dist/design-system/typography/index.d.ts +3 -0
  112. package/dist/design-system/typography/index.d.ts.map +1 -0
  113. package/dist/design-system/typography/index.js +3 -0
  114. package/dist/design-system/typography/index.js.map +1 -0
  115. package/dist/design-system/typography/tokens.d.ts +23 -0
  116. package/dist/design-system/typography/tokens.d.ts.map +1 -0
  117. package/dist/design-system/typography/tokens.js +99 -0
  118. package/dist/design-system/typography/tokens.js.map +1 -0
  119. package/dist/react/hooks/useCheckoutSuccessParams.d.ts +2 -0
  120. package/dist/react/hooks/useCheckoutSuccessParams.d.ts.map +1 -0
  121. package/dist/react/hooks/useCheckoutSuccessParams.js +5 -0
  122. package/dist/react/hooks/useCheckoutSuccessParams.js.map +1 -0
  123. package/dist/react/index.d.ts +25 -0
  124. package/dist/react/index.d.ts.map +1 -0
  125. package/dist/react/index.js +22 -0
  126. package/dist/react/index.js.map +1 -0
  127. package/dist/react/primitives/BillingGate.d.ts +8 -0
  128. package/dist/react/primitives/BillingGate.d.ts.map +1 -0
  129. package/dist/react/primitives/BillingGate.js +13 -0
  130. package/dist/react/primitives/BillingGate.js.map +1 -0
  131. package/dist/react/primitives/BillingToggle.d.ts +8 -0
  132. package/dist/react/primitives/BillingToggle.d.ts.map +1 -0
  133. package/dist/react/primitives/BillingToggle.js +12 -0
  134. package/dist/react/primitives/BillingToggle.js.map +1 -0
  135. package/dist/react/primitives/CheckoutButton.d.ts +11 -0
  136. package/dist/react/primitives/CheckoutButton.d.ts.map +1 -0
  137. package/dist/react/primitives/CheckoutButton.js +21 -0
  138. package/dist/react/primitives/CheckoutButton.js.map +1 -0
  139. package/dist/react/primitives/CheckoutSuccessSummary.d.ts +7 -0
  140. package/dist/react/primitives/CheckoutSuccessSummary.d.ts.map +1 -0
  141. package/dist/react/primitives/CheckoutSuccessSummary.js +11 -0
  142. package/dist/react/primitives/CheckoutSuccessSummary.js.map +1 -0
  143. package/dist/react/primitives/CustomerPortalButton.d.ts +8 -0
  144. package/dist/react/primitives/CustomerPortalButton.d.ts.map +1 -0
  145. package/dist/react/primitives/CustomerPortalButton.js +21 -0
  146. package/dist/react/primitives/CustomerPortalButton.js.map +1 -0
  147. package/dist/react/primitives/NumberInput.d.ts +11 -0
  148. package/dist/react/primitives/NumberInput.d.ts.map +1 -0
  149. package/dist/react/primitives/NumberInput.js +18 -0
  150. package/dist/react/primitives/NumberInput.js.map +1 -0
  151. package/dist/react/primitives/OneTimeCheckoutButton.d.ts +11 -0
  152. package/dist/react/primitives/OneTimeCheckoutButton.d.ts.map +1 -0
  153. package/dist/react/primitives/OneTimeCheckoutButton.js +4 -0
  154. package/dist/react/primitives/OneTimeCheckoutButton.js.map +1 -0
  155. package/dist/react/primitives/OneTimePaymentStatusBadge.d.ts +6 -0
  156. package/dist/react/primitives/OneTimePaymentStatusBadge.d.ts.map +1 -0
  157. package/dist/react/primitives/OneTimePaymentStatusBadge.js +11 -0
  158. package/dist/react/primitives/OneTimePaymentStatusBadge.js.map +1 -0
  159. package/dist/react/primitives/PaymentWarningBanner.d.ts +7 -0
  160. package/dist/react/primitives/PaymentWarningBanner.d.ts.map +1 -0
  161. package/dist/react/primitives/PaymentWarningBanner.js +18 -0
  162. package/dist/react/primitives/PaymentWarningBanner.js.map +1 -0
  163. package/dist/react/primitives/PricingCard.d.ts +37 -0
  164. package/dist/react/primitives/PricingCard.d.ts.map +1 -0
  165. package/dist/react/primitives/PricingCard.js +125 -0
  166. package/dist/react/primitives/PricingCard.js.map +1 -0
  167. package/dist/react/primitives/PricingSection.d.ts +39 -0
  168. package/dist/react/primitives/PricingSection.d.ts.map +1 -0
  169. package/dist/react/primitives/PricingSection.js +24 -0
  170. package/dist/react/primitives/PricingSection.js.map +1 -0
  171. package/dist/react/primitives/ScheduledChangeBanner.d.ts +8 -0
  172. package/dist/react/primitives/ScheduledChangeBanner.d.ts.map +1 -0
  173. package/dist/react/primitives/ScheduledChangeBanner.js +13 -0
  174. package/dist/react/primitives/ScheduledChangeBanner.js.map +1 -0
  175. package/dist/react/primitives/SegmentControl.d.ts +11 -0
  176. package/dist/react/primitives/SegmentControl.d.ts.map +1 -0
  177. package/dist/react/primitives/SegmentControl.js +8 -0
  178. package/dist/react/primitives/SegmentControl.js.map +1 -0
  179. package/dist/react/primitives/SegmentGroup.d.ts +14 -0
  180. package/dist/react/primitives/SegmentGroup.d.ts.map +1 -0
  181. package/dist/react/primitives/SegmentGroup.js +11 -0
  182. package/dist/react/primitives/SegmentGroup.js.map +1 -0
  183. package/dist/react/primitives/TrialLimitBanner.d.ts +7 -0
  184. package/dist/react/primitives/TrialLimitBanner.d.ts.map +1 -0
  185. package/dist/react/primitives/TrialLimitBanner.js +14 -0
  186. package/dist/react/primitives/TrialLimitBanner.js.map +1 -0
  187. package/dist/react/shared.d.ts +28 -0
  188. package/dist/react/shared.d.ts.map +1 -0
  189. package/dist/react/shared.js +109 -0
  190. package/dist/react/shared.js.map +1 -0
  191. package/dist/react/widgets/BillingPortal.d.ts +9 -0
  192. package/dist/react/widgets/BillingPortal.d.ts.map +1 -0
  193. package/dist/react/widgets/BillingPortal.js +30 -0
  194. package/dist/react/widgets/BillingPortal.js.map +1 -0
  195. package/dist/react/widgets/ProductItem.d.ts +8 -0
  196. package/dist/react/widgets/ProductItem.d.ts.map +1 -0
  197. package/dist/react/widgets/ProductItem.js +14 -0
  198. package/dist/react/widgets/ProductItem.js.map +1 -0
  199. package/dist/react/widgets/ProductRoot.d.ts +16 -0
  200. package/dist/react/widgets/ProductRoot.d.ts.map +1 -0
  201. package/dist/react/widgets/ProductRoot.js +171 -0
  202. package/dist/react/widgets/ProductRoot.js.map +1 -0
  203. package/dist/react/widgets/SubscriptionItem.d.ts +27 -0
  204. package/dist/react/widgets/SubscriptionItem.d.ts.map +1 -0
  205. package/dist/react/widgets/SubscriptionItem.js +32 -0
  206. package/dist/react/widgets/SubscriptionItem.js.map +1 -0
  207. package/dist/react/widgets/SubscriptionRoot.d.ts +16 -0
  208. package/dist/react/widgets/SubscriptionRoot.d.ts.map +1 -0
  209. package/dist/react/widgets/SubscriptionRoot.js +405 -0
  210. package/dist/react/widgets/SubscriptionRoot.js.map +1 -0
  211. package/dist/react/widgets/index.d.ts +19 -0
  212. package/dist/react/widgets/index.d.ts.map +1 -0
  213. package/dist/react/widgets/index.js +16 -0
  214. package/dist/react/widgets/index.js.map +1 -0
  215. package/dist/react/widgets/productGroupContext.d.ts +6 -0
  216. package/dist/react/widgets/productGroupContext.d.ts.map +1 -0
  217. package/dist/react/widgets/productGroupContext.js +3 -0
  218. package/dist/react/widgets/productGroupContext.js.map +1 -0
  219. package/dist/react/widgets/subscriptionContext.d.ts +6 -0
  220. package/dist/react/widgets/subscriptionContext.d.ts.map +1 -0
  221. package/dist/react/widgets/subscriptionContext.js +3 -0
  222. package/dist/react/widgets/subscriptionContext.js.map +1 -0
  223. package/dist/react/widgets/types.d.ts +171 -0
  224. package/dist/react/widgets/types.d.ts.map +1 -0
  225. package/dist/react/widgets/types.js +2 -0
  226. package/dist/react/widgets/types.js.map +1 -0
  227. package/dist/svelte/index.d.ts +22 -0
  228. package/dist/svelte/index.d.ts.map +1 -0
  229. package/dist/svelte/index.js +20 -0
  230. package/dist/svelte/index.js.map +1 -0
  231. package/dist/svelte/primitives/BillingGate.svelte +28 -0
  232. package/dist/svelte/primitives/BillingToggle.svelte +27 -0
  233. package/dist/svelte/primitives/CheckoutButton.svelte +60 -0
  234. package/dist/svelte/primitives/CheckoutSuccessSummary.svelte +34 -0
  235. package/dist/svelte/primitives/CustomerPortalButton.svelte +60 -0
  236. package/dist/svelte/primitives/NumberInput.svelte +71 -0
  237. package/dist/svelte/primitives/OneTimeCheckoutButton.svelte +37 -0
  238. package/dist/svelte/primitives/OneTimePaymentStatusBadge.svelte +20 -0
  239. package/dist/svelte/primitives/PaymentWarningBanner.svelte +30 -0
  240. package/dist/svelte/primitives/PricingCard.svelte +356 -0
  241. package/dist/svelte/primitives/PricingSection.svelte +121 -0
  242. package/dist/svelte/primitives/ScheduledChangeBanner.svelte +46 -0
  243. package/dist/svelte/primitives/SegmentControl.svelte +38 -0
  244. package/dist/svelte/primitives/SegmentGroup.svelte +52 -0
  245. package/dist/svelte/primitives/TrialLimitBanner.svelte +32 -0
  246. package/dist/svelte/primitives/shared.d.ts +13 -0
  247. package/dist/svelte/primitives/shared.d.ts.map +1 -0
  248. package/dist/svelte/primitives/shared.js +87 -0
  249. package/dist/svelte/primitives/shared.js.map +1 -0
  250. package/dist/svelte/widgets/BillingPortal.svelte +55 -0
  251. package/dist/svelte/widgets/Product.svelte +35 -0
  252. package/dist/svelte/widgets/ProductRoot.svelte +428 -0
  253. package/dist/svelte/widgets/Subscription.svelte +52 -0
  254. package/dist/svelte/widgets/SubscriptionRoot.svelte +690 -0
  255. package/dist/svelte/widgets/index.d.ts +19 -0
  256. package/dist/svelte/widgets/index.d.ts.map +1 -0
  257. package/dist/svelte/widgets/index.js +16 -0
  258. package/dist/svelte/widgets/index.js.map +1 -0
  259. package/dist/svelte/widgets/productGroupContext.d.ts +6 -0
  260. package/dist/svelte/widgets/productGroupContext.d.ts.map +1 -0
  261. package/dist/svelte/widgets/productGroupContext.js +2 -0
  262. package/dist/svelte/widgets/productGroupContext.js.map +1 -0
  263. package/dist/svelte/widgets/subscriptionContext.d.ts +6 -0
  264. package/dist/svelte/widgets/subscriptionContext.d.ts.map +1 -0
  265. package/dist/svelte/widgets/subscriptionContext.js +2 -0
  266. package/dist/svelte/widgets/subscriptionContext.js.map +1 -0
  267. package/dist/svelte/widgets/types.d.ts +171 -0
  268. package/dist/svelte/widgets/types.d.ts.map +1 -0
  269. package/dist/svelte/widgets/types.js +2 -0
  270. package/dist/svelte/widgets/types.js.map +1 -0
  271. package/package.json +182 -0
  272. package/src/client/helpers.test.ts +139 -0
  273. package/src/client/helpers.ts +51 -0
  274. package/src/client/index.test.ts +1554 -0
  275. package/src/client/index.ts +1504 -0
  276. package/src/client/parsers.test.ts +1017 -0
  277. package/src/client/parsers.ts +182 -0
  278. package/src/client/polyfill.ts +2 -0
  279. package/src/component/_generated/api.ts +52 -0
  280. package/src/component/_generated/component.ts +619 -0
  281. package/src/component/_generated/dataModel.ts +60 -0
  282. package/src/component/_generated/server.ts +156 -0
  283. package/src/component/convex.config.ts +3 -0
  284. package/src/component/lib.test.ts +1359 -0
  285. package/src/component/lib.ts +726 -0
  286. package/src/component/schema.ts +112 -0
  287. package/src/component/util.test.ts +281 -0
  288. package/src/component/util.ts +228 -0
  289. package/src/core/catalog.test.ts +212 -0
  290. package/src/core/catalog.ts +119 -0
  291. package/src/core/index.ts +8 -0
  292. package/src/core/markdown.test.ts +43 -0
  293. package/src/core/markdown.ts +26 -0
  294. package/src/core/payments.test.ts +69 -0
  295. package/src/core/payments.ts +33 -0
  296. package/src/core/pendingCheckout.test.ts +44 -0
  297. package/src/core/pendingCheckout.ts +40 -0
  298. package/src/core/resolver.test.ts +283 -0
  299. package/src/core/resolver.ts +160 -0
  300. package/src/core/selectors.test.ts +119 -0
  301. package/src/core/selectors.ts +35 -0
  302. package/src/core/subscriptionUpdate.test.ts +164 -0
  303. package/src/core/subscriptionUpdate.ts +102 -0
  304. package/src/core/types.ts +220 -0
  305. package/src/design-system/README.md +40 -0
  306. package/src/design-system/base.css +27 -0
  307. package/src/design-system/colors/color-utils.ts +110 -0
  308. package/src/design-system/colors/config.ts +282 -0
  309. package/src/design-system/colors/index.ts +2 -0
  310. package/src/design-system/colors/utilities.css +2328 -0
  311. package/src/design-system/components/badges.css +65 -0
  312. package/src/design-system/components/buttons.css +256 -0
  313. package/src/design-system/components/dialog.css +218 -0
  314. package/src/design-system/components/icon-buttons.css +115 -0
  315. package/src/design-system/components/inputs.css +94 -0
  316. package/src/design-system/components/links.css +53 -0
  317. package/src/design-system/components/prose.css +67 -0
  318. package/src/design-system/components/segment-control.css +303 -0
  319. package/src/design-system/index.css +21 -0
  320. package/src/design-system/rounded/config.ts +91 -0
  321. package/src/design-system/rounded/index.ts +1 -0
  322. package/src/design-system/rounded/utilities.css +37 -0
  323. package/src/design-system/typography/config.ts +340 -0
  324. package/src/design-system/typography/index.ts +2 -0
  325. package/src/design-system/typography/tokens.ts +148 -0
  326. package/src/design-system/typography/utilities.css +728 -0
  327. package/src/library.css +20 -0
  328. package/src/react/hooks/useCheckoutSuccessParams.ts +7 -0
  329. package/src/react/index.tsx +47 -0
  330. package/src/react/primitives/BillingGate.tsx +26 -0
  331. package/src/react/primitives/BillingToggle.tsx +29 -0
  332. package/src/react/primitives/CheckoutButton.tsx +47 -0
  333. package/src/react/primitives/CheckoutSuccessSummary.tsx +36 -0
  334. package/src/react/primitives/CustomerPortalButton.tsx +50 -0
  335. package/src/react/primitives/NumberInput.tsx +83 -0
  336. package/src/react/primitives/OneTimeCheckoutButton.tsx +27 -0
  337. package/src/react/primitives/OneTimePaymentStatusBadge.tsx +18 -0
  338. package/src/react/primitives/PaymentWarningBanner.tsx +33 -0
  339. package/src/react/primitives/PricingCard.tsx +421 -0
  340. package/src/react/primitives/PricingSection.tsx +129 -0
  341. package/src/react/primitives/ScheduledChangeBanner.tsx +52 -0
  342. package/src/react/primitives/SegmentControl.tsx +32 -0
  343. package/src/react/primitives/SegmentGroup.tsx +53 -0
  344. package/src/react/primitives/TrialLimitBanner.tsx +32 -0
  345. package/src/react/shared.ts +138 -0
  346. package/src/react/widgets/BillingPortal.tsx +56 -0
  347. package/src/react/widgets/ProductItem.tsx +26 -0
  348. package/src/react/widgets/ProductRoot.tsx +441 -0
  349. package/src/react/widgets/SubscriptionItem.tsx +71 -0
  350. package/src/react/widgets/SubscriptionRoot.tsx +759 -0
  351. package/src/react/widgets/index.ts +36 -0
  352. package/src/react/widgets/productGroupContext.ts +10 -0
  353. package/src/react/widgets/subscriptionContext.ts +10 -0
  354. package/src/react/widgets/types.ts +179 -0
  355. package/src/svelte/index.ts +43 -0
  356. package/src/svelte/primitives/BillingGate.svelte +28 -0
  357. package/src/svelte/primitives/BillingToggle.svelte +27 -0
  358. package/src/svelte/primitives/CheckoutButton.svelte +60 -0
  359. package/src/svelte/primitives/CheckoutSuccessSummary.svelte +34 -0
  360. package/src/svelte/primitives/CustomerPortalButton.svelte +60 -0
  361. package/src/svelte/primitives/NumberInput.svelte +71 -0
  362. package/src/svelte/primitives/OneTimeCheckoutButton.svelte +37 -0
  363. package/src/svelte/primitives/OneTimePaymentStatusBadge.svelte +20 -0
  364. package/src/svelte/primitives/PaymentWarningBanner.svelte +30 -0
  365. package/src/svelte/primitives/PricingCard.svelte +356 -0
  366. package/src/svelte/primitives/PricingSection.svelte +121 -0
  367. package/src/svelte/primitives/ScheduledChangeBanner.svelte +46 -0
  368. package/src/svelte/primitives/SegmentControl.svelte +38 -0
  369. package/src/svelte/primitives/SegmentGroup.svelte +52 -0
  370. package/src/svelte/primitives/TrialLimitBanner.svelte +32 -0
  371. package/src/svelte/primitives/shared.ts +113 -0
  372. package/src/svelte/svelte.d.ts +6 -0
  373. package/src/svelte/widgets/BillingPortal.svelte +55 -0
  374. package/src/svelte/widgets/Product.svelte +35 -0
  375. package/src/svelte/widgets/ProductRoot.svelte +428 -0
  376. package/src/svelte/widgets/Subscription.svelte +52 -0
  377. package/src/svelte/widgets/SubscriptionRoot.svelte +690 -0
  378. package/src/svelte/widgets/index.ts +36 -0
  379. package/src/svelte/widgets/productGroupContext.ts +7 -0
  380. package/src/svelte/widgets/subscriptionContext.ts +7 -0
  381. package/src/svelte/widgets/types.ts +179 -0
  382. package/src/tailwind.css +6 -0
  383. package/src/test.ts +18 -0
@@ -0,0 +1,36 @@
1
+ import { SubscriptionItem } from "./SubscriptionItem.js";
2
+ import { SubscriptionRoot } from "./SubscriptionRoot.js";
3
+ import { ProductItem } from "./ProductItem.js";
4
+ import { ProductRoot } from "./ProductRoot.js";
5
+
6
+ export { BillingPortal } from "./BillingPortal.js";
7
+
8
+ export const Subscription: typeof SubscriptionItem & {
9
+ Root: typeof SubscriptionRoot;
10
+ Item: typeof SubscriptionItem;
11
+ /** @deprecated Use `Subscription.Root` instead. */
12
+ Group: typeof SubscriptionRoot;
13
+ } = Object.assign(SubscriptionItem, {
14
+ Root: SubscriptionRoot,
15
+ Item: SubscriptionItem,
16
+ Group: SubscriptionRoot,
17
+ });
18
+
19
+ export const Product: typeof ProductItem & {
20
+ Root: typeof ProductRoot;
21
+ Item: typeof ProductItem;
22
+ /** @deprecated Use `Product.Root` instead. */
23
+ Group: typeof ProductRoot;
24
+ } = Object.assign(ProductItem, {
25
+ Root: ProductRoot,
26
+ Item: ProductItem,
27
+ Group: ProductRoot,
28
+ });
29
+
30
+ export type {
31
+ ConnectedBillingApi,
32
+ ConnectedBillingModel,
33
+ ProductType,
34
+ SubscriptionPlanType,
35
+ Transition,
36
+ } from "./types.js";
@@ -0,0 +1,10 @@
1
+ import { createContext } from "react";
2
+ import type { ProductItemRegistration } from "./types.js";
3
+
4
+ export type ProductGroupContextValue = {
5
+ registerItem: (item: ProductItemRegistration) => () => void;
6
+ };
7
+
8
+ export const ProductGroupContext = createContext<
9
+ ProductGroupContextValue | undefined
10
+ >(undefined);
@@ -0,0 +1,10 @@
1
+ import { createContext } from "react";
2
+ import type { SubscriptionPlanRegistration } from "./types.js";
3
+
4
+ export type SubscriptionContextValue = {
5
+ registerPlan: (plan: SubscriptionPlanRegistration) => () => void;
6
+ };
7
+
8
+ export const SubscriptionContext = createContext<
9
+ SubscriptionContextValue | undefined
10
+ >(undefined);
@@ -0,0 +1,179 @@
1
+ import type { FunctionReference } from "convex/server";
2
+ import type { BillingSnapshot, RecurringCycle } from "../../core/types.js";
3
+
4
+ export type { CheckoutIntent } from "../../core/types.js";
5
+
6
+ /**
7
+ * UI-side permission flags for billing widgets.
8
+ * Controls which buttons are enabled/visible. This is **cosmetic gating only** —
9
+ * enforce real permissions server-side in your Convex functions.
10
+ *
11
+ * When a permission is `false`, the corresponding button renders as disabled.
12
+ * When omitted or `undefined`, all actions default to enabled.
13
+ */
14
+ export type BillingPermissions = {
15
+ /** Allow creating new checkouts (subscribe / buy buttons). */
16
+ canCheckout?: boolean;
17
+ /** Allow switching plans or billing intervals. */
18
+ canChangeSubscription?: boolean;
19
+ /** Allow cancelling the active subscription. */
20
+ canCancelSubscription?: boolean;
21
+ /** Allow resuming a paused or scheduled-cancel subscription. */
22
+ canResumeSubscription?: boolean;
23
+ /** Allow changing the seat count on seat-based plans. */
24
+ canUpdateSeats?: boolean;
25
+ /** Allow opening the Creem customer billing portal. */
26
+ canAccessPortal?: boolean;
27
+ };
28
+
29
+ /**
30
+ * Backend function references for connected billing widgets.
31
+ * Created once in your layout/page and passed to `<Subscription.Root>`, `<Product.Root>`, and `<BillingPortal>`.
32
+ *
33
+ * All references point to Convex functions generated by `creem.api({ resolve })`
34
+ * or your own custom wrappers.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const billingApi: ConnectedBillingApi = {
39
+ * uiModel: api.billing.uiModel,
40
+ * checkouts: { create: api.billing.checkoutsCreate },
41
+ * subscriptions: {
42
+ * update: api.billing.subscriptionsUpdate,
43
+ * cancel: api.billing.subscriptionsCancel,
44
+ * resume: api.billing.subscriptionsResume,
45
+ * },
46
+ * customers: { portalUrl: api.billing.customersPortalUrl },
47
+ * };
48
+ * ```
49
+ */
50
+ export type ConnectedBillingApi = {
51
+ /** Query that returns the `ConnectedBillingModel` — called by all widgets to load billing state. */
52
+ uiModel: FunctionReference<"query">;
53
+ /** Checkout actions. */
54
+ checkouts: {
55
+ /** Create a checkout session and return `{ url }`. */
56
+ create: FunctionReference<"action">;
57
+ };
58
+ /** Subscription mutation references. All optional — omit to hide the corresponding UI controls. */
59
+ subscriptions?: {
60
+ /** Plan switch or seat update mutation. */
61
+ update?: FunctionReference<"mutation">;
62
+ /** Cancel subscription mutation. */
63
+ cancel?: FunctionReference<"mutation">;
64
+ /** Resume paused/scheduled-cancel subscription mutation. */
65
+ resume?: FunctionReference<"mutation">;
66
+ };
67
+ /** Customer actions. */
68
+ customers?: {
69
+ /** Action that returns `{ url }` for the Creem billing portal. */
70
+ portalUrl?: FunctionReference<"action">;
71
+ };
72
+ };
73
+
74
+ /** Product data as returned by the billing model query. Mirrors the Convex DB product schema. */
75
+ export type ConnectedProduct = {
76
+ id: string;
77
+ name?: string;
78
+ description?: string;
79
+ price?: number;
80
+ currency?: string;
81
+ billingType?: string;
82
+ billingPeriod?: string;
83
+ status?: string;
84
+ taxMode?: string;
85
+ taxCategory?: string;
86
+ imageUrl?: string;
87
+ features?: Array<{ id: string; description: string }>;
88
+ };
89
+
90
+ /**
91
+ * Complete billing state returned by the `uiModel` query.
92
+ * Consumed internally by all connected widgets — you typically don't need to access this directly.
93
+ */
94
+ export type ConnectedBillingModel = {
95
+ /** Authenticated user info, or `null` when unauthenticated (public pricing page). */
96
+ user: {
97
+ _id: string;
98
+ email: string;
99
+ isFree?: boolean;
100
+ isTrialing?: boolean;
101
+ trialEnd?: string | null;
102
+ } | null;
103
+ /** Resolved billing state (plan, status, available actions). `null` when unauthenticated. */
104
+ billingSnapshot: BillingSnapshot | null;
105
+ /** All synced products from the Creem dashboard. */
106
+ allProducts: ConnectedProduct[];
107
+ /** Product IDs the entity has purchased (one-time orders). */
108
+ ownedProductIds: string[];
109
+ /** Product ID of the current subscription, or `null`. */
110
+ subscriptionProductId: string | null;
111
+ /** All active subscriptions with full details. */
112
+ activeSubscriptions?: Array<{
113
+ id: string;
114
+ productId: string;
115
+ status: string;
116
+ cancelAtPeriodEnd: boolean;
117
+ currentPeriodEnd: string | null;
118
+ currentPeriodStart: string;
119
+ seats: number | null;
120
+ recurringInterval: string | null;
121
+ trialEnd?: string | null;
122
+ }>;
123
+ /** Whether this entity has a Creem customer record (needed for billing portal). */
124
+ hasCreemCustomer?: boolean;
125
+ /** Reserved for future billing policy data. */
126
+ policy?: unknown;
127
+ };
128
+
129
+ /**
130
+ * Plan type for `<Subscription.Item>`.
131
+ * - `"free"` — free tier, no checkout
132
+ * - `"single"` — standard paid plan (flat pricing)
133
+ * - `"seat-based"` — per-seat pricing with optional seat picker
134
+ * - `"enterprise"` — "Contact sales" CTA, no checkout
135
+ */
136
+ export type SubscriptionPlanType =
137
+ | "free"
138
+ | "single"
139
+ | "seat-based"
140
+ | "enterprise";
141
+
142
+ export type SubscriptionPlanRegistration = {
143
+ planId: string;
144
+ type: SubscriptionPlanType;
145
+ title?: string;
146
+ description?: string;
147
+ contactUrl?: string;
148
+ recommended?: boolean;
149
+ productIds?: Partial<Record<RecurringCycle, string>>;
150
+ };
151
+
152
+ /**
153
+ * Product type for `<Product.Item>`.
154
+ * - `"one-time"` — purchased once, shows "Owned" badge after purchase
155
+ * - `"recurring"` — can be purchased multiple times (consumable), no "Owned" badge
156
+ */
157
+ export type ProductType = "one-time" | "recurring";
158
+
159
+ /**
160
+ * Upgrade path rule for `<Product.Root transition={[...]}>`.
161
+ * - `"direct"` — checkout uses the target product directly
162
+ * - `"via_product"` — checkout uses a dedicated upgrade product (delta pricing)
163
+ */
164
+ export type Transition =
165
+ | { from: string; to: string; kind: "direct" }
166
+ | {
167
+ from: string;
168
+ to: string;
169
+ kind: "via_product";
170
+ /** Creem product ID for the upgrade (e.g. a delta-priced "Basic → Premium" product). */
171
+ viaProductId: string;
172
+ };
173
+
174
+ export type ProductItemRegistration = {
175
+ productId: string;
176
+ type: ProductType;
177
+ title?: string;
178
+ description?: string;
179
+ };
@@ -0,0 +1,43 @@
1
+ export {
2
+ parseCheckoutSuccessParams,
3
+ hasCheckoutSuccessParams,
4
+ } from "../core/payments.js";
5
+ export { pendingCheckout } from "../core/pendingCheckout.js";
6
+ export { default as BillingToggle } from "./primitives/BillingToggle.svelte";
7
+ export { default as SegmentGroup } from "./primitives/SegmentGroup.svelte";
8
+ export { default as SegmentControl } from "./primitives/SegmentControl.svelte";
9
+ export { default as NumberInput } from "./primitives/NumberInput.svelte";
10
+ export { default as CheckoutButton } from "./primitives/CheckoutButton.svelte";
11
+ export { default as CustomerPortalButton } from "./primitives/CustomerPortalButton.svelte";
12
+ export { default as PricingCard } from "./primitives/PricingCard.svelte";
13
+ export { default as PricingSection } from "./primitives/PricingSection.svelte";
14
+ export { default as BillingGate } from "./primitives/BillingGate.svelte";
15
+ export { default as ScheduledChangeBanner } from "./primitives/ScheduledChangeBanner.svelte";
16
+ export { default as PaymentWarningBanner } from "./primitives/PaymentWarningBanner.svelte";
17
+ export { default as TrialLimitBanner } from "./primitives/TrialLimitBanner.svelte";
18
+ export { default as OneTimeCheckoutButton } from "./primitives/OneTimeCheckoutButton.svelte";
19
+ export { default as OneTimePaymentStatusBadge } from "./primitives/OneTimePaymentStatusBadge.svelte";
20
+ export { default as CheckoutSuccessSummary } from "./primitives/CheckoutSuccessSummary.svelte";
21
+ export { Subscription, Product, BillingPortal } from "./widgets/index.js";
22
+ export type {
23
+ BillingSnapshot,
24
+ CheckoutSuccessParams,
25
+ OneTimePaymentStatus,
26
+ RecurringCycle,
27
+ } from "../core/types.js";
28
+ export {
29
+ hasBillingAction,
30
+ isEnterpriseBilling,
31
+ isOneTimeBilling,
32
+ isTerminalPaymentStatus,
33
+ shouldShowBillingCycleToggle,
34
+ } from "../core/selectors.js";
35
+ export type {
36
+ BillingPermissions,
37
+ CheckoutIntent,
38
+ ConnectedBillingApi,
39
+ ConnectedBillingModel,
40
+ ProductType,
41
+ SubscriptionPlanType,
42
+ Transition,
43
+ } from "./widgets/types.js";
@@ -0,0 +1,28 @@
1
+ <script lang="ts">
2
+ /* global $props, $derived */
3
+ import type { Snippet } from "svelte";
4
+ import type { AvailableAction, BillingSnapshot } from "../../core/types.js";
5
+ import { hasBillingActionLocal } from "./shared.js";
6
+
7
+ interface Props {
8
+ snapshot?: BillingSnapshot | null;
9
+ requiredActions: AvailableAction | AvailableAction[];
10
+ children?: Snippet;
11
+ fallback?: Snippet;
12
+ }
13
+
14
+ let { snapshot, requiredActions, children, fallback }: Props = $props();
15
+
16
+ const actions = $derived(
17
+ Array.isArray(requiredActions) ? requiredActions : [requiredActions],
18
+ );
19
+ const canRender = $derived(
20
+ snapshot != null && actions.every((action) => hasBillingActionLocal(snapshot, action)),
21
+ );
22
+ </script>
23
+
24
+ {#if canRender}
25
+ {@render children?.()}
26
+ {:else}
27
+ {@render fallback?.()}
28
+ {/if}
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ /* global $props */
3
+ import type { RecurringCycle } from "../../core/types.js";
4
+ import { formatRecurringCycle } from "./shared.js";
5
+ import SegmentGroup from "./SegmentGroup.svelte";
6
+
7
+ interface Props {
8
+ cycles?: RecurringCycle[];
9
+ value?: RecurringCycle;
10
+ onValueChange?: (cycle: RecurringCycle) => void;
11
+ className?: string;
12
+ }
13
+
14
+ let { cycles = [], value, onValueChange, className = "" }: Props = $props();
15
+ </script>
16
+
17
+ {#if cycles.length > 1}
18
+ <SegmentGroup
19
+ items={cycles.map((cycle) => ({
20
+ value: cycle,
21
+ label: formatRecurringCycle(cycle),
22
+ }))}
23
+ value={value}
24
+ onValueChange={(segment) => onValueChange?.(segment as RecurringCycle)}
25
+ className={className}
26
+ />
27
+ {/if}
@@ -0,0 +1,60 @@
1
+ <script lang="ts">
2
+ /* global $props, $state */
3
+ import type { Snippet } from "svelte";
4
+
5
+ interface Props {
6
+ productId: string;
7
+ href?: string;
8
+ disabled?: boolean;
9
+ className?: string;
10
+ onCheckout?: (payload: { productId: string }) => Promise<void> | void;
11
+ children?: Snippet;
12
+ }
13
+
14
+ let {
15
+ productId,
16
+ href = undefined,
17
+ disabled = false,
18
+ className = "",
19
+ onCheckout,
20
+ children,
21
+ }: Props = $props();
22
+
23
+ let isLoading = $state(false);
24
+
25
+ const handleClick = async () => {
26
+ if (disabled || isLoading || !onCheckout) return;
27
+ isLoading = true;
28
+ try {
29
+ await onCheckout({ productId });
30
+ } finally {
31
+ isLoading = false;
32
+ }
33
+ };
34
+ </script>
35
+
36
+ {#if onCheckout}
37
+ <button
38
+ type="button"
39
+ class={`button-filled disabled:cursor-not-allowed disabled:opacity-60 ${className}`}
40
+ {disabled}
41
+ onclick={handleClick}
42
+ >
43
+ {#if children}
44
+ {@render children()}
45
+ {:else}
46
+ {isLoading ? "Loading..." : "Checkout"}
47
+ {/if}
48
+ </button>
49
+ {:else}
50
+ <a
51
+ href={href}
52
+ class={`button-filled ${className}`}
53
+ >
54
+ {#if children}
55
+ {@render children()}
56
+ {:else}
57
+ Checkout
58
+ {/if}
59
+ </a>
60
+ {/if}
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ /* global $props, $derived */
3
+ import {
4
+ hasCheckoutSuccessParams,
5
+ parseCheckoutSuccessParams,
6
+ } from "../../core/payments.js";
7
+ import type { CheckoutSuccessParams } from "../../core/types.js";
8
+
9
+ interface Props {
10
+ params?: CheckoutSuccessParams;
11
+ search?: string;
12
+ class?: string;
13
+ }
14
+
15
+ let { params = undefined, search = "", class: className = "" }: Props = $props();
16
+
17
+ const parsed = $derived(params ?? parseCheckoutSuccessParams(search));
18
+ const show = $derived(hasCheckoutSuccessParams(parsed));
19
+ </script>
20
+
21
+ {#if show}
22
+ <div
23
+ class={`rounded-lg border border-emerald-300 bg-emerald-50 px-4 py-3 text-sm text-emerald-900 dark:border-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-200 ${className}`}
24
+ >
25
+ <p class="font-medium">Checkout completed successfully.</p>
26
+ <ul class="mt-2 space-y-1">
27
+ {#if parsed.checkoutId}<li>Checkout: {parsed.checkoutId}</li>{/if}
28
+ {#if parsed.orderId}<li>Order: {parsed.orderId}</li>{/if}
29
+ {#if parsed.customerId}<li>Customer: {parsed.customerId}</li>{/if}
30
+ {#if parsed.productId}<li>Product: {parsed.productId}</li>{/if}
31
+ {#if parsed.requestId}<li>Request: {parsed.requestId}</li>{/if}
32
+ </ul>
33
+ </div>
34
+ {/if}
@@ -0,0 +1,60 @@
1
+ <script lang="ts">
2
+ /* global $props, $state */
3
+ import type { Snippet } from "svelte";
4
+
5
+ interface Props {
6
+ href?: string;
7
+ disabled?: boolean;
8
+ className?: string;
9
+ onOpenPortal?: () => Promise<void> | void;
10
+ children?: Snippet;
11
+ }
12
+
13
+ let {
14
+ href = undefined,
15
+ disabled = false,
16
+ className = "",
17
+ onOpenPortal,
18
+ children,
19
+ }: Props = $props();
20
+
21
+ let isLoading = $state(false);
22
+
23
+ const handleClick = async () => {
24
+ if (disabled || isLoading || !onOpenPortal) return;
25
+ isLoading = true;
26
+ try {
27
+ await onOpenPortal();
28
+ } finally {
29
+ isLoading = false;
30
+ }
31
+ };
32
+ </script>
33
+
34
+ {#if onOpenPortal}
35
+ <button
36
+ type="button"
37
+ class={`${className || "button-outline"} disabled:cursor-not-allowed disabled:opacity-60 cursor-pointer`}
38
+ {disabled}
39
+ onclick={handleClick}
40
+ >
41
+ {#if children}
42
+ {@render children()}
43
+ {:else}
44
+ {isLoading ? "Loading..." : "Manage billing"}
45
+ {/if}
46
+ </button>
47
+ {:else}
48
+ <a
49
+ href={href}
50
+ target="_blank"
51
+ rel="noopener noreferrer"
52
+ class={`${className || "button-outline"}`}
53
+ >
54
+ {#if children}
55
+ {@render children()}
56
+ {:else}
57
+ Manage billing
58
+ {/if}
59
+ </a>
60
+ {/if}
@@ -0,0 +1,71 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ value?: number;
4
+ min?: number;
5
+ max?: number;
6
+ step?: number;
7
+ compact?: boolean;
8
+ disabled?: boolean;
9
+ className?: string;
10
+ onValueChange?: (value: number) => void | Promise<void>;
11
+ }
12
+
13
+ let {
14
+ value = 1,
15
+ min = Number.NEGATIVE_INFINITY,
16
+ max = Number.POSITIVE_INFINITY,
17
+ step = 1,
18
+ compact = false,
19
+ disabled = false,
20
+ className = "",
21
+ onValueChange,
22
+ }: Props = $props();
23
+
24
+ const clamp = (candidate: number) => Math.min(max, Math.max(min, candidate));
25
+
26
+ const setValue = (candidate: number) => {
27
+ const next = clamp(candidate);
28
+ onValueChange?.(next);
29
+ };
30
+
31
+ const decrement = () => setValue((value ?? 0) - step);
32
+ const increment = () => setValue((value ?? 0) + step);
33
+ </script>
34
+
35
+ <div class={`number-input ${className}`}>
36
+ <button
37
+ type="button"
38
+ aria-label="Decrease value"
39
+ {disabled}
40
+ class="icon-button-sm"
41
+ onclick={decrement}
42
+ >
43
+ <svg aria-hidden="true" viewBox="0 0 256 256" fill="currentColor" class="h-4 w-4 text-foreground-on-tonal">
44
+ <path d="M216,128a12,12,0,0,1-12,12H52a12,12,0,0,1,0-24H204A12,12,0,0,1,216,128Z" />
45
+ </svg>
46
+ </button>
47
+
48
+ <input
49
+ type="number"
50
+ class={`input-ghost ${compact ? "number-input-value-compact" : "number-input-value"} max-w-12 input-no-spinner`}
51
+ value={value}
52
+ {disabled}
53
+ oninput={(event) => {
54
+ const parsed = Number((event.currentTarget as HTMLInputElement).value);
55
+ if (!Number.isFinite(parsed)) return;
56
+ setValue(parsed);
57
+ }}
58
+ />
59
+
60
+ <button
61
+ type="button"
62
+ aria-label="Increase value"
63
+ {disabled}
64
+ class="icon-button-sm"
65
+ onclick={increment}
66
+ >
67
+ <svg aria-hidden="true" viewBox="0 0 256 256" fill="currentColor" class="h-4 w-4 text-foreground-on-tonal">
68
+ <path d="M216,128a12,12,0,0,1-12,12H140v64a12,12,0,0,1-24,0V140H52a12,12,0,0,1,0-24h64V52a12,12,0,0,1,24,0v64h64A12,12,0,0,1,216,128Z" />
69
+ </svg>
70
+ </button>
71
+ </div>
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ /* global $props */
3
+ import type { Snippet } from "svelte";
4
+ import CheckoutButton from "./CheckoutButton.svelte";
5
+
6
+ interface Props {
7
+ productId: string;
8
+ href?: string;
9
+ disabled?: boolean;
10
+ className?: string;
11
+ onCheckout?: (payload: { productId: string }) => Promise<void> | void;
12
+ children?: Snippet;
13
+ }
14
+
15
+ let {
16
+ productId,
17
+ href = undefined,
18
+ disabled = false,
19
+ className = "",
20
+ onCheckout,
21
+ children,
22
+ }: Props = $props();
23
+ </script>
24
+
25
+ <CheckoutButton
26
+ {productId}
27
+ {href}
28
+ {disabled}
29
+ {className}
30
+ {onCheckout}
31
+ >
32
+ {#if children}
33
+ {@render children()}
34
+ {:else}
35
+ Buy now
36
+ {/if}
37
+ </CheckoutButton>
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ /* global $props */
3
+ import type { OneTimePaymentStatus } from "../../core/types.js";
4
+
5
+ interface Props {
6
+ status: OneTimePaymentStatus;
7
+ className?: string;
8
+ }
9
+
10
+ let { status, className = "" }: Props = $props();
11
+
12
+ const labels: Record<OneTimePaymentStatus, string> = {
13
+ pending: "Pending",
14
+ paid: "Paid",
15
+ refunded: "Refunded",
16
+ partially_refunded: "Partially refunded",
17
+ };
18
+ </script>
19
+
20
+ <span class={className}>{labels[status]}</span>
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ /* global $props, $derived */
3
+ import type { BillingSnapshot, PaymentSnapshot } from "../../core/types.js";
4
+
5
+ interface Props {
6
+ snapshot?: BillingSnapshot | null;
7
+ payment?: PaymentSnapshot | null;
8
+ className?: string;
9
+ }
10
+
11
+ let { snapshot = null, payment = null, className = "" }: Props = $props();
12
+
13
+ const activePayment = $derived(payment ?? snapshot?.payment ?? null);
14
+ const show = $derived(activePayment != null && activePayment.status !== "paid");
15
+ const message = $derived(
16
+ activePayment?.status === "pending"
17
+ ? "Your payment is pending confirmation. Wait for webhook confirmation before granting permanent access."
18
+ : activePayment?.status === "partially_refunded"
19
+ ? "This payment was partially refunded. Review entitlements that depend on purchase amount."
20
+ : "This payment was refunded. Access should generally be revoked or downgraded.",
21
+ );
22
+ </script>
23
+
24
+ {#if show}
25
+ <div
26
+ class={`rounded-lg border border-rose-300 bg-rose-50 px-4 py-3 text-sm text-rose-900 dark:border-rose-800 dark:bg-rose-950/40 dark:text-rose-200 ${className}`}
27
+ >
28
+ {message}
29
+ </div>
30
+ {/if}