@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,690 @@
1
+ <script lang="ts">
2
+ import { setContext, untrack } from "svelte";
3
+ import { SvelteSet } from "svelte/reactivity";
4
+
5
+ import { Dialog } from "@ark-ui/svelte/dialog";
6
+ import { Portal } from "@ark-ui/svelte/portal";
7
+
8
+ import PricingSection from "../primitives/PricingSection.svelte";
9
+ import PaymentWarningBanner from "../primitives/PaymentWarningBanner.svelte";
10
+ import ScheduledChangeBanner from "../primitives/ScheduledChangeBanner.svelte";
11
+
12
+ import { useConvexClient, useQuery } from "convex-svelte";
13
+ import {
14
+ SUBSCRIPTION_CONTEXT_KEY,
15
+ type SubscriptionContextValue,
16
+ } from "./subscriptionContext.js";
17
+ import { pendingCheckout } from "../../core/pendingCheckout.js";
18
+
19
+ import type { UIPlanEntry, RecurringCycle, UpdateBehavior } from "../../core/types.js";
20
+ import { buildUpdateSummary } from "../../core/subscriptionUpdate.js";
21
+ import { formatPriceWithInterval, formatSeatPrice } from "../primitives/shared.js";
22
+ import type {
23
+ BillingPermissions,
24
+ CheckoutIntent,
25
+ ConnectedBillingApi,
26
+ ConnectedBillingModel,
27
+ SubscriptionPlanRegistration,
28
+ } from "./types.js";
29
+
30
+ interface Props {
31
+ api: ConnectedBillingApi;
32
+ permissions?: BillingPermissions;
33
+ class?: string;
34
+ successUrl?: string;
35
+ units?: number;
36
+ showSeatPicker?: boolean;
37
+ twoColumnLayout?: boolean;
38
+ updateBehavior?: UpdateBehavior;
39
+ onBeforeCheckout?: (intent: CheckoutIntent) => Promise<boolean> | boolean;
40
+ children?: import("svelte").Snippet;
41
+ }
42
+
43
+ let {
44
+ api,
45
+ permissions = undefined,
46
+ class: className = "",
47
+ successUrl = undefined,
48
+ units = undefined,
49
+ showSeatPicker = false,
50
+ twoColumnLayout = false,
51
+ updateBehavior = "proration-charge-immediately",
52
+ onBeforeCheckout = undefined,
53
+ children,
54
+ }: Props = $props();
55
+
56
+ const canChange = $derived(permissions?.canChangeSubscription !== false);
57
+ const canCancel = $derived(permissions?.canCancelSubscription !== false);
58
+ const canResume = $derived(permissions?.canResumeSubscription !== false);
59
+
60
+ const client = useConvexClient();
61
+
62
+ // svelte-ignore state_referenced_locally
63
+ const billingUiModelRef = api.uiModel;
64
+ // svelte-ignore state_referenced_locally
65
+ const checkoutLinkRef = api.checkouts.create;
66
+ // svelte-ignore state_referenced_locally
67
+ const updateRef = api.subscriptions?.update;
68
+ // svelte-ignore state_referenced_locally
69
+ const cancelRef = api.subscriptions?.cancel;
70
+ // svelte-ignore state_referenced_locally
71
+ const resumeRef = api.subscriptions?.resume;
72
+
73
+ const billingModelQuery = useQuery(billingUiModelRef, {});
74
+
75
+ let selectedCycle = $state<RecurringCycle>("every-month");
76
+ let isActionLoading = $state(false);
77
+ let actionError = $state<string | null>(null);
78
+ let updateDialogOpen = $state(false);
79
+ let pendingUpdate = $state<
80
+ | { kind: "plan-switch"; plan: UIPlanEntry; productId: string; units?: number }
81
+ | { kind: "seat-update"; units: number }
82
+ | null
83
+ >(null);
84
+ let registeredPlans = $state<SubscriptionPlanRegistration[]>([]);
85
+ let cancelDialogOpen = $state(false);
86
+
87
+ const contextValue: SubscriptionContextValue = {
88
+ registerPlan: (plan) => {
89
+ registeredPlans = [
90
+ ...registeredPlans.filter(
91
+ (candidate) => candidate.planId !== plan.planId,
92
+ ),
93
+ plan,
94
+ ];
95
+ return () => {
96
+ registeredPlans = registeredPlans.filter(
97
+ (candidate) => candidate.planId !== plan.planId,
98
+ );
99
+ };
100
+ },
101
+ };
102
+
103
+ setContext(SUBSCRIPTION_CONTEXT_KEY, contextValue);
104
+
105
+ const model = $derived(
106
+ (billingModelQuery.data ?? null) as ConnectedBillingModel | null,
107
+ );
108
+ const canCheckout = $derived(
109
+ !model?.user && onBeforeCheckout != null
110
+ ? true
111
+ : permissions?.canCheckout !== false,
112
+ );
113
+ const canUpdateSeats = $derived(
114
+ !model?.user && onBeforeCheckout != null
115
+ ? true
116
+ : permissions?.canUpdateSeats !== false,
117
+ );
118
+ const snapshot = $derived(model?.billingSnapshot ?? null);
119
+
120
+ $effect(() => {
121
+ if (!model?.user) return;
122
+ untrack(() => {
123
+ const pending = pendingCheckout.load();
124
+ if (!pending) return;
125
+ if ((model!.activeSubscriptions ?? []).length > 0) {
126
+ pendingCheckout.clear();
127
+ return;
128
+ }
129
+ startCheckout(pending.productId, pending.units);
130
+ });
131
+ });
132
+
133
+ const activePlanId = $derived.by<string | null>(() => {
134
+ if (!model) return null;
135
+ // Use this component's matched subscription product ID, not the global one
136
+ const subProductId = localSubscriptionProductId;
137
+ if (subProductId) {
138
+ const matchedPlan = registeredPlans.find((plan) => {
139
+ const values = Object.values(plan.productIds ?? {}).filter(
140
+ Boolean,
141
+ ) as string[];
142
+ return values.includes(subProductId);
143
+ });
144
+ return matchedPlan?.planId ?? null;
145
+ }
146
+ // No active subscription — if user is signed in, treat the free plan as active
147
+ if (model.user) {
148
+ const freePlan = plans.find((p) => p.category === "free");
149
+ if (freePlan) return freePlan.planId;
150
+ }
151
+ return null;
152
+ });
153
+
154
+ const allProducts = $derived(model?.allProducts ?? []);
155
+
156
+ const plansFromRegistered = $derived.by<UIPlanEntry[]>(() => {
157
+ return registeredPlans.map((plan) => {
158
+ const productIds = plan.productIds ?? {};
159
+ const firstProductId = Object.values(productIds)[0];
160
+ const firstProduct = firstProductId
161
+ ? allProducts.find((p) => p.id === firstProductId)
162
+ : undefined;
163
+
164
+ const cycleKeys = Object.keys(productIds).filter(
165
+ (k): k is RecurringCycle => k !== "custom",
166
+ );
167
+
168
+ const entry: UIPlanEntry = {
169
+ planId: plan.planId,
170
+ category:
171
+ plan.type === "free"
172
+ ? "free"
173
+ : plan.type === "enterprise"
174
+ ? "enterprise"
175
+ : "paid",
176
+ billingType:
177
+ plan.type === "free" || plan.type === "enterprise"
178
+ ? "custom"
179
+ : "recurring",
180
+ pricingModel: plan.type === "seat-based" ? "seat" : "flat",
181
+ title:
182
+ plan.title ??
183
+ firstProduct?.name ??
184
+ plan.planId.charAt(0).toUpperCase() + plan.planId.slice(1),
185
+ description: plan.description ?? firstProduct?.description ?? undefined,
186
+ contactUrl: plan.contactUrl,
187
+ recommended: plan.recommended,
188
+ creemProductIds:
189
+ Object.keys(productIds).length > 0
190
+ ? (productIds as Record<string, string>)
191
+ : undefined,
192
+ };
193
+ if (cycleKeys.length > 0) {
194
+ entry.billingCycles = cycleKeys;
195
+ }
196
+ return entry;
197
+ });
198
+ });
199
+
200
+ const plans = $derived(plansFromRegistered);
201
+
202
+ // Collect all product IDs that belong to plans in THIS component instance.
203
+ const ownProductIds = $derived.by<Set<string>>(() => {
204
+ const ids = new SvelteSet<string>();
205
+ for (const plan of plans) {
206
+ if (plan.creemProductIds) {
207
+ for (const pid of Object.values(plan.creemProductIds)) {
208
+ if (pid) ids.add(pid);
209
+ }
210
+ }
211
+ }
212
+ return ids;
213
+ });
214
+
215
+ // Find the subscription from activeSubscriptions that belongs to THIS component.
216
+ const matchedSubscription = $derived.by(() => {
217
+ const subs = model?.activeSubscriptions;
218
+ if (!subs || ownProductIds.size === 0) return null;
219
+ return subs.find((s) => ownProductIds.has(s.productId)) ?? null;
220
+ });
221
+
222
+ const ownsActiveSubscription = $derived(matchedSubscription != null);
223
+ const localSubscriptionProductId = $derived(
224
+ matchedSubscription?.productId ?? null,
225
+ );
226
+ const localCancelAtPeriodEnd = $derived(
227
+ matchedSubscription?.cancelAtPeriodEnd ?? false,
228
+ );
229
+ const localCurrentPeriodEnd = $derived(
230
+ matchedSubscription?.currentPeriodEnd ?? null,
231
+ );
232
+ const localSubscriptionState = $derived(matchedSubscription?.status ?? null);
233
+ const localSubscribedSeats = $derived(matchedSubscription?.seats ?? null);
234
+
235
+ const getFallbackSuccessUrl = (): string | undefined => {
236
+ if (typeof window === "undefined") return undefined;
237
+ return `${window.location.origin}${window.location.pathname}`;
238
+ };
239
+
240
+ const getPreferredTheme = (): "light" | "dark" => {
241
+ if (typeof window === "undefined") return "light";
242
+ return window.matchMedia("(prefers-color-scheme: dark)").matches
243
+ ? "dark"
244
+ : "light";
245
+ };
246
+
247
+ const startCheckout = async (productId: string, checkoutUnits?: number) => {
248
+ if (onBeforeCheckout) {
249
+ const proceed = await onBeforeCheckout({
250
+ productId,
251
+ units: checkoutUnits,
252
+ });
253
+ if (!proceed) return;
254
+ }
255
+ isActionLoading = true;
256
+ actionError = null;
257
+ try {
258
+ const { url } = await client.action(checkoutLinkRef, {
259
+ productId,
260
+ ...(successUrl ? { successUrl } : {}),
261
+ fallbackSuccessUrl: getFallbackSuccessUrl(),
262
+ theme: getPreferredTheme(),
263
+ ...(checkoutUnits != null ? { units: checkoutUnits } : {}),
264
+ });
265
+ // Suppress Convex client's beforeunload dialog during checkout redirect.
266
+ // Convex registers via addEventListener, so onbeforeunload=null has no effect.
267
+ // A capture-phase listener fires before non-capture listeners on the same target
268
+ // in modern browsers, and stopImmediatePropagation() blocks all subsequent handlers.
269
+ window.addEventListener(
270
+ "beforeunload",
271
+ (e) => {
272
+ e.stopImmediatePropagation();
273
+ },
274
+ { capture: true, once: true },
275
+ );
276
+ window.location.href = url;
277
+ window.location.href = url;
278
+ } catch (error) {
279
+ actionError = error instanceof Error ? error.message : "Checkout failed";
280
+ } finally {
281
+ isActionLoading = false;
282
+ }
283
+ };
284
+
285
+ const handlePricingCheckout = async (payload: {
286
+ plan: UIPlanEntry;
287
+ productId: string;
288
+ units?: number;
289
+ }) => {
290
+ await startCheckout(payload.productId, payload.units);
291
+ };
292
+
293
+ const requestSwitchPlan = (payload: {
294
+ plan: UIPlanEntry;
295
+ productId: string;
296
+ units?: number;
297
+ }) => {
298
+ pendingUpdate = { kind: "plan-switch", ...payload };
299
+ updateDialogOpen = true;
300
+ };
301
+
302
+ const confirmUpdate = async () => {
303
+ if (!updateRef || !pendingUpdate) return;
304
+ const update = pendingUpdate;
305
+ const subId = matchedSubscription?.id;
306
+ updateDialogOpen = false;
307
+ pendingUpdate = null;
308
+ actionError = null;
309
+ try {
310
+ if (update.kind === "plan-switch") {
311
+ await client.mutation(
312
+ updateRef,
313
+ {
314
+ productId: update.productId,
315
+ ...(subId ? { subscriptionId: subId } : {}),
316
+ updateBehavior,
317
+ },
318
+ {
319
+ optimisticUpdate: (store) => {
320
+ const current = store.getQuery(billingUiModelRef, {});
321
+ if (current) {
322
+ const m = current as ConnectedBillingModel;
323
+ store.setQuery(
324
+ billingUiModelRef,
325
+ {},
326
+ {
327
+ ...m,
328
+ activeSubscriptions: (m.activeSubscriptions ?? []).map((s) =>
329
+ ownProductIds.has(s.productId)
330
+ ? { ...s, productId: update.productId }
331
+ : s,
332
+ ),
333
+ },
334
+ );
335
+ }
336
+ },
337
+ },
338
+ );
339
+ } else {
340
+ await client.mutation(
341
+ updateRef,
342
+ {
343
+ units: update.units,
344
+ ...(subId ? { subscriptionId: subId } : {}),
345
+ updateBehavior,
346
+ },
347
+ {
348
+ optimisticUpdate: (store) => {
349
+ const current = store.getQuery(billingUiModelRef, {});
350
+ if (current) {
351
+ const m = current as ConnectedBillingModel;
352
+ store.setQuery(
353
+ billingUiModelRef,
354
+ {},
355
+ {
356
+ ...m,
357
+ activeSubscriptions: (m.activeSubscriptions ?? []).map((s) =>
358
+ s.id === subId ? { ...s, seats: update.units } : s,
359
+ ),
360
+ },
361
+ );
362
+ }
363
+ },
364
+ },
365
+ );
366
+ }
367
+ } catch (error) {
368
+ actionError = error instanceof Error
369
+ ? error.message
370
+ : update.kind === "plan-switch"
371
+ ? "Switch failed"
372
+ : "Seat update failed";
373
+ }
374
+ };
375
+
376
+ const handleUpdateSeats = (payload: { units: number }) => {
377
+ pendingUpdate = { kind: "seat-update", units: payload.units };
378
+ updateDialogOpen = true;
379
+ };
380
+
381
+ const updateSummary = $derived.by(() => {
382
+ if (!pendingUpdate) return null;
383
+
384
+ if (pendingUpdate.kind === "plan-switch") {
385
+ const currentPlan = plans.find((p) => {
386
+ const pids = p.creemProductIds ? Object.values(p.creemProductIds) : [];
387
+ return localSubscriptionProductId != null && pids.includes(localSubscriptionProductId);
388
+ });
389
+ const currentTitle = currentPlan?.title ?? "Current plan";
390
+ const currentPrice = formatPriceWithInterval(localSubscriptionProductId ?? undefined, allProducts);
391
+ const newPrice = formatPriceWithInterval(pendingUpdate.productId, allProducts);
392
+
393
+ return buildUpdateSummary({
394
+ kind: "plan-switch",
395
+ updateBehavior,
396
+ currentLabel: currentPrice ? `${currentTitle} \u00b7 ${currentPrice}` : currentTitle,
397
+ newLabel: newPrice
398
+ ? `${pendingUpdate.plan.title ?? "New plan"} \u00b7 ${newPrice}`
399
+ : (pendingUpdate.plan.title ?? "New plan"),
400
+ currentPeriodEnd: matchedSubscription?.currentPeriodEnd,
401
+ isTrialing: matchedSubscription?.status === "trialing",
402
+ trialEnd: matchedSubscription?.trialEnd,
403
+ });
404
+ }
405
+
406
+ const currentSeats = localSubscribedSeats ?? 1;
407
+ const currentPrice = formatSeatPrice(localSubscriptionProductId ?? undefined, allProducts, currentSeats);
408
+ const newPrice = formatSeatPrice(localSubscriptionProductId ?? undefined, allProducts, pendingUpdate.units);
409
+
410
+ return buildUpdateSummary({
411
+ kind: "seat-update",
412
+ updateBehavior,
413
+ currentLabel: currentPrice ?? `${currentSeats} seat${currentSeats !== 1 ? "s" : ""}`,
414
+ newLabel: newPrice ?? `${pendingUpdate.units} seat${pendingUpdate.units !== 1 ? "s" : ""}`,
415
+ currentPeriodEnd: matchedSubscription?.currentPeriodEnd,
416
+ isTrialing: matchedSubscription?.status === "trialing",
417
+ trialEnd: matchedSubscription?.trialEnd,
418
+ });
419
+ });
420
+
421
+ const confirmCancelSubscription = async () => {
422
+ if (!cancelRef) return;
423
+ const subId = matchedSubscription?.id;
424
+ cancelDialogOpen = false;
425
+ actionError = null;
426
+ try {
427
+ await client.mutation(
428
+ cancelRef,
429
+ {
430
+ ...(subId ? { subscriptionId: subId } : {}),
431
+ },
432
+ {
433
+ optimisticUpdate: (store) => {
434
+ const current = store.getQuery(billingUiModelRef, {});
435
+ if (current) {
436
+ const m = current as ConnectedBillingModel;
437
+ store.setQuery(
438
+ billingUiModelRef,
439
+ {},
440
+ {
441
+ ...m,
442
+ activeSubscriptions: (m.activeSubscriptions ?? []).map((s) =>
443
+ ownProductIds.has(s.productId)
444
+ ? { ...s, cancelAtPeriodEnd: true }
445
+ : s,
446
+ ),
447
+ },
448
+ );
449
+ }
450
+ },
451
+ },
452
+ );
453
+ } catch (error) {
454
+ actionError = error instanceof Error ? error.message : "Cancel failed";
455
+ }
456
+ };
457
+
458
+ const resumeSubscription = async () => {
459
+ if (!resumeRef) return;
460
+ const subId = matchedSubscription?.id;
461
+ actionError = null;
462
+ try {
463
+ await client.mutation(
464
+ resumeRef,
465
+ {
466
+ ...(subId ? { subscriptionId: subId } : {}),
467
+ },
468
+ {
469
+ optimisticUpdate: (store) => {
470
+ const current = store.getQuery(billingUiModelRef, {});
471
+ if (current) {
472
+ const m = current as ConnectedBillingModel;
473
+ store.setQuery(
474
+ billingUiModelRef,
475
+ {},
476
+ {
477
+ ...m,
478
+ activeSubscriptions: (m.activeSubscriptions ?? []).map((s) =>
479
+ ownProductIds.has(s.productId)
480
+ ? { ...s, cancelAtPeriodEnd: false, status: "active" }
481
+ : s,
482
+ ),
483
+ },
484
+ );
485
+ }
486
+ },
487
+ },
488
+ );
489
+ } catch (error) {
490
+ actionError = error instanceof Error ? error.message : "Resume failed";
491
+ }
492
+ };
493
+
494
+ const openCancelDialog = () => {
495
+ cancelDialogOpen = true;
496
+ };
497
+ </script>
498
+
499
+ <div class="hidden" aria-hidden="true">
500
+ {@render children?.()}
501
+ </div>
502
+
503
+ <section class={`space-y-4 ${className}`}>
504
+ {#if actionError}
505
+ <div
506
+ class="rounded-lg border border-red-300 bg-red-50 px-3 py-2 text-sm text-red-700"
507
+ >
508
+ {actionError}
509
+ </div>
510
+ {/if}
511
+
512
+ {#if !model}
513
+ <p class="text-sm text-zinc-500">Loading billing model…</p>
514
+ {:else}
515
+ {#if ownsActiveSubscription && snapshot}
516
+ <ScheduledChangeBanner
517
+ snapshot={{
518
+ ...snapshot,
519
+ metadata: {
520
+ ...snapshot.metadata,
521
+ cancelAtPeriodEnd: localCancelAtPeriodEnd,
522
+ currentPeriodEnd: localCurrentPeriodEnd,
523
+ },
524
+ }}
525
+ isLoading={isActionLoading}
526
+ onResume={resumeRef && canResume ? resumeSubscription : undefined}
527
+ />
528
+ {/if}
529
+ <PaymentWarningBanner {snapshot} />
530
+
531
+ <PricingSection
532
+ {plans}
533
+ snapshot={snapshot ? { ...snapshot, activePlanId } : null}
534
+ {selectedCycle}
535
+ products={allProducts}
536
+ subscriptionProductId={localSubscriptionProductId}
537
+ subscriptionStatus={localSubscriptionState}
538
+ subscriptionTrialEnd={matchedSubscription?.trialEnd ?? null}
539
+ {units}
540
+ {showSeatPicker}
541
+ {twoColumnLayout}
542
+ subscribedSeats={localSubscribedSeats}
543
+ isGroupSubscribed={ownsActiveSubscription}
544
+ onCycleChange={(cycle) => {
545
+ selectedCycle = cycle;
546
+ }}
547
+ disableCheckout={!canCheckout}
548
+ disableSwitch={!canChange}
549
+ disableSeats={!canUpdateSeats}
550
+ onCheckout={canCheckout ? handlePricingCheckout : undefined}
551
+ onSwitchPlan={updateRef && canChange ? requestSwitchPlan : undefined}
552
+ onUpdateSeats={updateRef && canUpdateSeats
553
+ ? handleUpdateSeats
554
+ : undefined}
555
+ onCancelSubscription={cancelRef &&
556
+ canCancel &&
557
+ ownsActiveSubscription &&
558
+ !localCancelAtPeriodEnd
559
+ ? openCancelDialog
560
+ : undefined}
561
+ />
562
+
563
+ <div class="flex flex-wrap items-center gap-3">
564
+ {#if children}
565
+ {@render children()}
566
+ {/if}
567
+ </div>
568
+
569
+ <Dialog.Root
570
+ open={cancelDialogOpen}
571
+ onOpenChange={(details: { open: boolean }) => {
572
+ cancelDialogOpen = details.open;
573
+ }}
574
+ >
575
+ <Portal>
576
+ <Dialog.Backdrop class="dialog-backdrop" />
577
+ <Dialog.Positioner class="dialog-positioner">
578
+ <Dialog.Content class="dialog-content">
579
+ <Dialog.CloseTrigger
580
+ class="icon-button-ghost-sm absolute right-2 top-2"
581
+ aria-label="Close dialog"
582
+ >
583
+ <svg
584
+ aria-hidden="true"
585
+ viewBox="0 0 24 24"
586
+ fill="none"
587
+ class="h-4 w-4"
588
+ >
589
+ <path
590
+ d="M18 6L6 18M6 6L18 18"
591
+ stroke="currentColor"
592
+ stroke-width="1.5"
593
+ stroke-linecap="round"
594
+ stroke-linejoin="round"
595
+ />
596
+ </svg>
597
+ </Dialog.CloseTrigger>
598
+ <Dialog.Title class="dialog-title">
599
+ Cancel subscription?
600
+ </Dialog.Title>
601
+ <Dialog.Description class="dialog-description">
602
+ Are you sure you want to cancel your subscription? You will
603
+ continue to have access until the end of your current billing
604
+ period.
605
+ </Dialog.Description>
606
+ <div class="dialog-actions">
607
+ <button
608
+ type="button"
609
+ class="dialog-action-danger"
610
+ onclick={() => confirmCancelSubscription()}
611
+ >
612
+ Yes, cancel
613
+ </button>
614
+ <Dialog.CloseTrigger class="button-faded h-8 w-full">
615
+ Keep subscription
616
+ </Dialog.CloseTrigger>
617
+ </div>
618
+ </Dialog.Content>
619
+ </Dialog.Positioner>
620
+ </Portal>
621
+ </Dialog.Root>
622
+
623
+ <Dialog.Root
624
+ open={updateDialogOpen}
625
+ onOpenChange={(details: { open: boolean }) => {
626
+ updateDialogOpen = details.open;
627
+ if (!details.open) pendingUpdate = null;
628
+ }}
629
+ >
630
+ <Portal>
631
+ <Dialog.Backdrop class="dialog-backdrop" />
632
+ <Dialog.Positioner class="dialog-positioner">
633
+ <Dialog.Content class="dialog-content">
634
+ <Dialog.CloseTrigger
635
+ class="icon-button-ghost-sm absolute right-2 top-2"
636
+ aria-label="Close dialog"
637
+ >
638
+ <svg
639
+ aria-hidden="true"
640
+ viewBox="0 0 24 24"
641
+ fill="none"
642
+ class="h-4 w-4"
643
+ >
644
+ <path
645
+ d="M18 6L6 18M6 6L18 18"
646
+ stroke="currentColor"
647
+ stroke-width="1.5"
648
+ stroke-linecap="round"
649
+ stroke-linejoin="round"
650
+ />
651
+ </svg>
652
+ </Dialog.CloseTrigger>
653
+ <Dialog.Title class="dialog-title">
654
+ {updateSummary?.title}
655
+ </Dialog.Title>
656
+ {#if updateSummary}
657
+ <div class="my-3 flex flex-col gap-1 rounded-lg bg-surface-subtle px-3 py-2.5">
658
+ <span class="label-m text-foreground-muted">
659
+ {updateSummary.currentLabel}
660
+ </span>
661
+ <span class="body-s text-foreground-placeholder">→</span>
662
+ <span class="label-m text-foreground-default">
663
+ {updateSummary.newLabel}
664
+ </span>
665
+ </div>
666
+ <Dialog.Description class="dialog-description">
667
+ {updateSummary.description}
668
+ {#if updateSummary.dateNote}
669
+ {` ${updateSummary.dateNote}`}
670
+ {/if}
671
+ </Dialog.Description>
672
+ {/if}
673
+ <div class="dialog-actions">
674
+ <button
675
+ type="button"
676
+ class="button-filled h-8 w-full"
677
+ onclick={() => confirmUpdate()}
678
+ >
679
+ {updateSummary?.confirmLabel ?? "Confirm"}
680
+ </button>
681
+ <Dialog.CloseTrigger class="button-faded h-8 w-full">
682
+ Cancel
683
+ </Dialog.CloseTrigger>
684
+ </div>
685
+ </Dialog.Content>
686
+ </Dialog.Positioner>
687
+ </Portal>
688
+ </Dialog.Root>
689
+ {/if}
690
+ </section>
@@ -0,0 +1,19 @@
1
+ import SubscriptionItemComponent from "./Subscription.svelte";
2
+ import SubscriptionRootComponent from "./SubscriptionRoot.svelte";
3
+ import ProductItemComponent from "./Product.svelte";
4
+ import ProductRootComponent from "./ProductRoot.svelte";
5
+ export { default as BillingPortal } from "./BillingPortal.svelte";
6
+ export declare const Subscription: typeof SubscriptionItemComponent & {
7
+ Root: typeof SubscriptionRootComponent;
8
+ Item: typeof SubscriptionItemComponent;
9
+ /** @deprecated Use `Subscription.Root` instead. */
10
+ Group: typeof SubscriptionRootComponent;
11
+ };
12
+ export declare const Product: typeof ProductItemComponent & {
13
+ Root: typeof ProductRootComponent;
14
+ Item: typeof ProductItemComponent;
15
+ /** @deprecated Use `Product.Root` instead. */
16
+ Group: typeof ProductRootComponent;
17
+ };
18
+ export type { ConnectedBillingApi, ConnectedBillingModel, ProductType, SubscriptionPlanType, Transition, } from "./types.js";
19
+ //# sourceMappingURL=index.d.ts.map