@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.
- package/LICENSE +201 -0
- package/README.md +1176 -0
- package/dist/client/helpers.d.ts +17 -0
- package/dist/client/helpers.d.ts.map +1 -0
- package/dist/client/helpers.js +43 -0
- package/dist/client/helpers.js.map +1 -0
- package/dist/client/index.d.ts +1041 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +1068 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/parsers.d.ts +45 -0
- package/dist/client/parsers.d.ts.map +1 -0
- package/dist/client/parsers.js +138 -0
- package/dist/client/parsers.js.map +1 -0
- package/dist/client/polyfill.d.ts +2 -0
- package/dist/client/polyfill.d.ts.map +1 -0
- package/dist/client/polyfill.js +3 -0
- package/dist/client/polyfill.js.map +1 -0
- package/dist/component/_generated/api.d.ts +36 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +31 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +542 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +46 -0
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +121 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +78 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/convex.config.d.ts +3 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +3 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/lib.d.ts +1005 -0
- package/dist/component/lib.d.ts.map +1 -0
- package/dist/component/lib.js +647 -0
- package/dist/component/lib.js.map +1 -0
- package/dist/component/schema.d.ts +191 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +104 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/component/util.d.ts +61 -0
- package/dist/component/util.d.ts.map +1 -0
- package/dist/component/util.js +142 -0
- package/dist/component/util.js.map +1 -0
- package/dist/core/catalog.d.ts +18 -0
- package/dist/core/catalog.d.ts.map +1 -0
- package/dist/core/catalog.js +82 -0
- package/dist/core/catalog.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/markdown.d.ts +12 -0
- package/dist/core/markdown.d.ts.map +1 -0
- package/dist/core/markdown.js +26 -0
- package/dist/core/markdown.js.map +1 -0
- package/dist/core/payments.d.ts +11 -0
- package/dist/core/payments.d.ts.map +1 -0
- package/dist/core/payments.js +27 -0
- package/dist/core/payments.js.map +1 -0
- package/dist/core/pendingCheckout.d.ts +15 -0
- package/dist/core/pendingCheckout.d.ts.map +1 -0
- package/dist/core/pendingCheckout.js +40 -0
- package/dist/core/pendingCheckout.js.map +1 -0
- package/dist/core/resolver.d.ts +11 -0
- package/dist/core/resolver.d.ts.map +1 -0
- package/dist/core/resolver.js +106 -0
- package/dist/core/resolver.js.map +1 -0
- package/dist/core/selectors.d.ts +12 -0
- package/dist/core/selectors.d.ts.map +1 -0
- package/dist/core/selectors.js +18 -0
- package/dist/core/selectors.js.map +1 -0
- package/dist/core/subscriptionUpdate.d.ts +20 -0
- package/dist/core/subscriptionUpdate.d.ts.map +1 -0
- package/dist/core/subscriptionUpdate.js +64 -0
- package/dist/core/subscriptionUpdate.js.map +1 -0
- package/dist/core/types.d.ts +170 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +15 -0
- package/dist/core/types.js.map +1 -0
- package/dist/design-system/colors/color-utils.d.ts +10 -0
- package/dist/design-system/colors/color-utils.d.ts.map +1 -0
- package/dist/design-system/colors/color-utils.js +91 -0
- package/dist/design-system/colors/color-utils.js.map +1 -0
- package/dist/design-system/colors/config.d.ts +33 -0
- package/dist/design-system/colors/config.d.ts.map +1 -0
- package/dist/design-system/colors/config.js +224 -0
- package/dist/design-system/colors/config.js.map +1 -0
- package/dist/design-system/colors/index.d.ts +3 -0
- package/dist/design-system/colors/index.d.ts.map +1 -0
- package/dist/design-system/colors/index.js +3 -0
- package/dist/design-system/colors/index.js.map +1 -0
- package/dist/design-system/rounded/config.d.ts +31 -0
- package/dist/design-system/rounded/config.d.ts.map +1 -0
- package/dist/design-system/rounded/config.js +76 -0
- package/dist/design-system/rounded/config.js.map +1 -0
- package/dist/design-system/rounded/index.d.ts +2 -0
- package/dist/design-system/rounded/index.d.ts.map +1 -0
- package/dist/design-system/rounded/index.js +2 -0
- package/dist/design-system/rounded/index.js.map +1 -0
- package/dist/design-system/typography/config.d.ts +55 -0
- package/dist/design-system/typography/config.d.ts.map +1 -0
- package/dist/design-system/typography/config.js +308 -0
- package/dist/design-system/typography/config.js.map +1 -0
- package/dist/design-system/typography/index.d.ts +3 -0
- package/dist/design-system/typography/index.d.ts.map +1 -0
- package/dist/design-system/typography/index.js +3 -0
- package/dist/design-system/typography/index.js.map +1 -0
- package/dist/design-system/typography/tokens.d.ts +23 -0
- package/dist/design-system/typography/tokens.d.ts.map +1 -0
- package/dist/design-system/typography/tokens.js +99 -0
- package/dist/design-system/typography/tokens.js.map +1 -0
- package/dist/react/hooks/useCheckoutSuccessParams.d.ts +2 -0
- package/dist/react/hooks/useCheckoutSuccessParams.d.ts.map +1 -0
- package/dist/react/hooks/useCheckoutSuccessParams.js +5 -0
- package/dist/react/hooks/useCheckoutSuccessParams.js.map +1 -0
- package/dist/react/index.d.ts +25 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +22 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/primitives/BillingGate.d.ts +8 -0
- package/dist/react/primitives/BillingGate.d.ts.map +1 -0
- package/dist/react/primitives/BillingGate.js +13 -0
- package/dist/react/primitives/BillingGate.js.map +1 -0
- package/dist/react/primitives/BillingToggle.d.ts +8 -0
- package/dist/react/primitives/BillingToggle.d.ts.map +1 -0
- package/dist/react/primitives/BillingToggle.js +12 -0
- package/dist/react/primitives/BillingToggle.js.map +1 -0
- package/dist/react/primitives/CheckoutButton.d.ts +11 -0
- package/dist/react/primitives/CheckoutButton.d.ts.map +1 -0
- package/dist/react/primitives/CheckoutButton.js +21 -0
- package/dist/react/primitives/CheckoutButton.js.map +1 -0
- package/dist/react/primitives/CheckoutSuccessSummary.d.ts +7 -0
- package/dist/react/primitives/CheckoutSuccessSummary.d.ts.map +1 -0
- package/dist/react/primitives/CheckoutSuccessSummary.js +11 -0
- package/dist/react/primitives/CheckoutSuccessSummary.js.map +1 -0
- package/dist/react/primitives/CustomerPortalButton.d.ts +8 -0
- package/dist/react/primitives/CustomerPortalButton.d.ts.map +1 -0
- package/dist/react/primitives/CustomerPortalButton.js +21 -0
- package/dist/react/primitives/CustomerPortalButton.js.map +1 -0
- package/dist/react/primitives/NumberInput.d.ts +11 -0
- package/dist/react/primitives/NumberInput.d.ts.map +1 -0
- package/dist/react/primitives/NumberInput.js +18 -0
- package/dist/react/primitives/NumberInput.js.map +1 -0
- package/dist/react/primitives/OneTimeCheckoutButton.d.ts +11 -0
- package/dist/react/primitives/OneTimeCheckoutButton.d.ts.map +1 -0
- package/dist/react/primitives/OneTimeCheckoutButton.js +4 -0
- package/dist/react/primitives/OneTimeCheckoutButton.js.map +1 -0
- package/dist/react/primitives/OneTimePaymentStatusBadge.d.ts +6 -0
- package/dist/react/primitives/OneTimePaymentStatusBadge.d.ts.map +1 -0
- package/dist/react/primitives/OneTimePaymentStatusBadge.js +11 -0
- package/dist/react/primitives/OneTimePaymentStatusBadge.js.map +1 -0
- package/dist/react/primitives/PaymentWarningBanner.d.ts +7 -0
- package/dist/react/primitives/PaymentWarningBanner.d.ts.map +1 -0
- package/dist/react/primitives/PaymentWarningBanner.js +18 -0
- package/dist/react/primitives/PaymentWarningBanner.js.map +1 -0
- package/dist/react/primitives/PricingCard.d.ts +37 -0
- package/dist/react/primitives/PricingCard.d.ts.map +1 -0
- package/dist/react/primitives/PricingCard.js +125 -0
- package/dist/react/primitives/PricingCard.js.map +1 -0
- package/dist/react/primitives/PricingSection.d.ts +39 -0
- package/dist/react/primitives/PricingSection.d.ts.map +1 -0
- package/dist/react/primitives/PricingSection.js +24 -0
- package/dist/react/primitives/PricingSection.js.map +1 -0
- package/dist/react/primitives/ScheduledChangeBanner.d.ts +8 -0
- package/dist/react/primitives/ScheduledChangeBanner.d.ts.map +1 -0
- package/dist/react/primitives/ScheduledChangeBanner.js +13 -0
- package/dist/react/primitives/ScheduledChangeBanner.js.map +1 -0
- package/dist/react/primitives/SegmentControl.d.ts +11 -0
- package/dist/react/primitives/SegmentControl.d.ts.map +1 -0
- package/dist/react/primitives/SegmentControl.js +8 -0
- package/dist/react/primitives/SegmentControl.js.map +1 -0
- package/dist/react/primitives/SegmentGroup.d.ts +14 -0
- package/dist/react/primitives/SegmentGroup.d.ts.map +1 -0
- package/dist/react/primitives/SegmentGroup.js +11 -0
- package/dist/react/primitives/SegmentGroup.js.map +1 -0
- package/dist/react/primitives/TrialLimitBanner.d.ts +7 -0
- package/dist/react/primitives/TrialLimitBanner.d.ts.map +1 -0
- package/dist/react/primitives/TrialLimitBanner.js +14 -0
- package/dist/react/primitives/TrialLimitBanner.js.map +1 -0
- package/dist/react/shared.d.ts +28 -0
- package/dist/react/shared.d.ts.map +1 -0
- package/dist/react/shared.js +109 -0
- package/dist/react/shared.js.map +1 -0
- package/dist/react/widgets/BillingPortal.d.ts +9 -0
- package/dist/react/widgets/BillingPortal.d.ts.map +1 -0
- package/dist/react/widgets/BillingPortal.js +30 -0
- package/dist/react/widgets/BillingPortal.js.map +1 -0
- package/dist/react/widgets/ProductItem.d.ts +8 -0
- package/dist/react/widgets/ProductItem.d.ts.map +1 -0
- package/dist/react/widgets/ProductItem.js +14 -0
- package/dist/react/widgets/ProductItem.js.map +1 -0
- package/dist/react/widgets/ProductRoot.d.ts +16 -0
- package/dist/react/widgets/ProductRoot.d.ts.map +1 -0
- package/dist/react/widgets/ProductRoot.js +171 -0
- package/dist/react/widgets/ProductRoot.js.map +1 -0
- package/dist/react/widgets/SubscriptionItem.d.ts +27 -0
- package/dist/react/widgets/SubscriptionItem.d.ts.map +1 -0
- package/dist/react/widgets/SubscriptionItem.js +32 -0
- package/dist/react/widgets/SubscriptionItem.js.map +1 -0
- package/dist/react/widgets/SubscriptionRoot.d.ts +16 -0
- package/dist/react/widgets/SubscriptionRoot.d.ts.map +1 -0
- package/dist/react/widgets/SubscriptionRoot.js +405 -0
- package/dist/react/widgets/SubscriptionRoot.js.map +1 -0
- package/dist/react/widgets/index.d.ts +19 -0
- package/dist/react/widgets/index.d.ts.map +1 -0
- package/dist/react/widgets/index.js +16 -0
- package/dist/react/widgets/index.js.map +1 -0
- package/dist/react/widgets/productGroupContext.d.ts +6 -0
- package/dist/react/widgets/productGroupContext.d.ts.map +1 -0
- package/dist/react/widgets/productGroupContext.js +3 -0
- package/dist/react/widgets/productGroupContext.js.map +1 -0
- package/dist/react/widgets/subscriptionContext.d.ts +6 -0
- package/dist/react/widgets/subscriptionContext.d.ts.map +1 -0
- package/dist/react/widgets/subscriptionContext.js +3 -0
- package/dist/react/widgets/subscriptionContext.js.map +1 -0
- package/dist/react/widgets/types.d.ts +171 -0
- package/dist/react/widgets/types.d.ts.map +1 -0
- package/dist/react/widgets/types.js +2 -0
- package/dist/react/widgets/types.js.map +1 -0
- package/dist/svelte/index.d.ts +22 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +20 -0
- package/dist/svelte/index.js.map +1 -0
- package/dist/svelte/primitives/BillingGate.svelte +28 -0
- package/dist/svelte/primitives/BillingToggle.svelte +27 -0
- package/dist/svelte/primitives/CheckoutButton.svelte +60 -0
- package/dist/svelte/primitives/CheckoutSuccessSummary.svelte +34 -0
- package/dist/svelte/primitives/CustomerPortalButton.svelte +60 -0
- package/dist/svelte/primitives/NumberInput.svelte +71 -0
- package/dist/svelte/primitives/OneTimeCheckoutButton.svelte +37 -0
- package/dist/svelte/primitives/OneTimePaymentStatusBadge.svelte +20 -0
- package/dist/svelte/primitives/PaymentWarningBanner.svelte +30 -0
- package/dist/svelte/primitives/PricingCard.svelte +356 -0
- package/dist/svelte/primitives/PricingSection.svelte +121 -0
- package/dist/svelte/primitives/ScheduledChangeBanner.svelte +46 -0
- package/dist/svelte/primitives/SegmentControl.svelte +38 -0
- package/dist/svelte/primitives/SegmentGroup.svelte +52 -0
- package/dist/svelte/primitives/TrialLimitBanner.svelte +32 -0
- package/dist/svelte/primitives/shared.d.ts +13 -0
- package/dist/svelte/primitives/shared.d.ts.map +1 -0
- package/dist/svelte/primitives/shared.js +87 -0
- package/dist/svelte/primitives/shared.js.map +1 -0
- package/dist/svelte/widgets/BillingPortal.svelte +55 -0
- package/dist/svelte/widgets/Product.svelte +35 -0
- package/dist/svelte/widgets/ProductRoot.svelte +428 -0
- package/dist/svelte/widgets/Subscription.svelte +52 -0
- package/dist/svelte/widgets/SubscriptionRoot.svelte +690 -0
- package/dist/svelte/widgets/index.d.ts +19 -0
- package/dist/svelte/widgets/index.d.ts.map +1 -0
- package/dist/svelte/widgets/index.js +16 -0
- package/dist/svelte/widgets/index.js.map +1 -0
- package/dist/svelte/widgets/productGroupContext.d.ts +6 -0
- package/dist/svelte/widgets/productGroupContext.d.ts.map +1 -0
- package/dist/svelte/widgets/productGroupContext.js +2 -0
- package/dist/svelte/widgets/productGroupContext.js.map +1 -0
- package/dist/svelte/widgets/subscriptionContext.d.ts +6 -0
- package/dist/svelte/widgets/subscriptionContext.d.ts.map +1 -0
- package/dist/svelte/widgets/subscriptionContext.js +2 -0
- package/dist/svelte/widgets/subscriptionContext.js.map +1 -0
- package/dist/svelte/widgets/types.d.ts +171 -0
- package/dist/svelte/widgets/types.d.ts.map +1 -0
- package/dist/svelte/widgets/types.js +2 -0
- package/dist/svelte/widgets/types.js.map +1 -0
- package/package.json +182 -0
- package/src/client/helpers.test.ts +139 -0
- package/src/client/helpers.ts +51 -0
- package/src/client/index.test.ts +1554 -0
- package/src/client/index.ts +1504 -0
- package/src/client/parsers.test.ts +1017 -0
- package/src/client/parsers.ts +182 -0
- package/src/client/polyfill.ts +2 -0
- package/src/component/_generated/api.ts +52 -0
- package/src/component/_generated/component.ts +619 -0
- package/src/component/_generated/dataModel.ts +60 -0
- package/src/component/_generated/server.ts +156 -0
- package/src/component/convex.config.ts +3 -0
- package/src/component/lib.test.ts +1359 -0
- package/src/component/lib.ts +726 -0
- package/src/component/schema.ts +112 -0
- package/src/component/util.test.ts +281 -0
- package/src/component/util.ts +228 -0
- package/src/core/catalog.test.ts +212 -0
- package/src/core/catalog.ts +119 -0
- package/src/core/index.ts +8 -0
- package/src/core/markdown.test.ts +43 -0
- package/src/core/markdown.ts +26 -0
- package/src/core/payments.test.ts +69 -0
- package/src/core/payments.ts +33 -0
- package/src/core/pendingCheckout.test.ts +44 -0
- package/src/core/pendingCheckout.ts +40 -0
- package/src/core/resolver.test.ts +283 -0
- package/src/core/resolver.ts +160 -0
- package/src/core/selectors.test.ts +119 -0
- package/src/core/selectors.ts +35 -0
- package/src/core/subscriptionUpdate.test.ts +164 -0
- package/src/core/subscriptionUpdate.ts +102 -0
- package/src/core/types.ts +220 -0
- package/src/design-system/README.md +40 -0
- package/src/design-system/base.css +27 -0
- package/src/design-system/colors/color-utils.ts +110 -0
- package/src/design-system/colors/config.ts +282 -0
- package/src/design-system/colors/index.ts +2 -0
- package/src/design-system/colors/utilities.css +2328 -0
- package/src/design-system/components/badges.css +65 -0
- package/src/design-system/components/buttons.css +256 -0
- package/src/design-system/components/dialog.css +218 -0
- package/src/design-system/components/icon-buttons.css +115 -0
- package/src/design-system/components/inputs.css +94 -0
- package/src/design-system/components/links.css +53 -0
- package/src/design-system/components/prose.css +67 -0
- package/src/design-system/components/segment-control.css +303 -0
- package/src/design-system/index.css +21 -0
- package/src/design-system/rounded/config.ts +91 -0
- package/src/design-system/rounded/index.ts +1 -0
- package/src/design-system/rounded/utilities.css +37 -0
- package/src/design-system/typography/config.ts +340 -0
- package/src/design-system/typography/index.ts +2 -0
- package/src/design-system/typography/tokens.ts +148 -0
- package/src/design-system/typography/utilities.css +728 -0
- package/src/library.css +20 -0
- package/src/react/hooks/useCheckoutSuccessParams.ts +7 -0
- package/src/react/index.tsx +47 -0
- package/src/react/primitives/BillingGate.tsx +26 -0
- package/src/react/primitives/BillingToggle.tsx +29 -0
- package/src/react/primitives/CheckoutButton.tsx +47 -0
- package/src/react/primitives/CheckoutSuccessSummary.tsx +36 -0
- package/src/react/primitives/CustomerPortalButton.tsx +50 -0
- package/src/react/primitives/NumberInput.tsx +83 -0
- package/src/react/primitives/OneTimeCheckoutButton.tsx +27 -0
- package/src/react/primitives/OneTimePaymentStatusBadge.tsx +18 -0
- package/src/react/primitives/PaymentWarningBanner.tsx +33 -0
- package/src/react/primitives/PricingCard.tsx +421 -0
- package/src/react/primitives/PricingSection.tsx +129 -0
- package/src/react/primitives/ScheduledChangeBanner.tsx +52 -0
- package/src/react/primitives/SegmentControl.tsx +32 -0
- package/src/react/primitives/SegmentGroup.tsx +53 -0
- package/src/react/primitives/TrialLimitBanner.tsx +32 -0
- package/src/react/shared.ts +138 -0
- package/src/react/widgets/BillingPortal.tsx +56 -0
- package/src/react/widgets/ProductItem.tsx +26 -0
- package/src/react/widgets/ProductRoot.tsx +441 -0
- package/src/react/widgets/SubscriptionItem.tsx +71 -0
- package/src/react/widgets/SubscriptionRoot.tsx +759 -0
- package/src/react/widgets/index.ts +36 -0
- package/src/react/widgets/productGroupContext.ts +10 -0
- package/src/react/widgets/subscriptionContext.ts +10 -0
- package/src/react/widgets/types.ts +179 -0
- package/src/svelte/index.ts +43 -0
- package/src/svelte/primitives/BillingGate.svelte +28 -0
- package/src/svelte/primitives/BillingToggle.svelte +27 -0
- package/src/svelte/primitives/CheckoutButton.svelte +60 -0
- package/src/svelte/primitives/CheckoutSuccessSummary.svelte +34 -0
- package/src/svelte/primitives/CustomerPortalButton.svelte +60 -0
- package/src/svelte/primitives/NumberInput.svelte +71 -0
- package/src/svelte/primitives/OneTimeCheckoutButton.svelte +37 -0
- package/src/svelte/primitives/OneTimePaymentStatusBadge.svelte +20 -0
- package/src/svelte/primitives/PaymentWarningBanner.svelte +30 -0
- package/src/svelte/primitives/PricingCard.svelte +356 -0
- package/src/svelte/primitives/PricingSection.svelte +121 -0
- package/src/svelte/primitives/ScheduledChangeBanner.svelte +46 -0
- package/src/svelte/primitives/SegmentControl.svelte +38 -0
- package/src/svelte/primitives/SegmentGroup.svelte +52 -0
- package/src/svelte/primitives/TrialLimitBanner.svelte +32 -0
- package/src/svelte/primitives/shared.ts +113 -0
- package/src/svelte/svelte.d.ts +6 -0
- package/src/svelte/widgets/BillingPortal.svelte +55 -0
- package/src/svelte/widgets/Product.svelte +35 -0
- package/src/svelte/widgets/ProductRoot.svelte +428 -0
- package/src/svelte/widgets/Subscription.svelte +52 -0
- package/src/svelte/widgets/SubscriptionRoot.svelte +690 -0
- package/src/svelte/widgets/index.ts +36 -0
- package/src/svelte/widgets/productGroupContext.ts +7 -0
- package/src/svelte/widgets/subscriptionContext.ts +7 -0
- package/src/svelte/widgets/types.ts +179 -0
- package/src/tailwind.css +6 -0
- 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}
|