@doujins/payments-ui 0.0.10 → 0.0.11

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/dist/index.cjs CHANGED
@@ -2685,6 +2685,245 @@ var PaymentExperience = ({
2685
2685
  )
2686
2686
  ] });
2687
2687
  };
2688
+ var SubscriptionSuccessDialog = ({
2689
+ open,
2690
+ planName = "Premium Plan",
2691
+ amountLabel = "$0.00",
2692
+ billingPeriodLabel = "billing period",
2693
+ onClose
2694
+ }) => {
2695
+ return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: (value) => {
2696
+ if (!value) onClose();
2697
+ }, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-w-sm text-center", children: [
2698
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
2699
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex flex-col items-center gap-3 text-foreground", children: [
2700
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "h-10 w-10 text-primary" }),
2701
+ "Subscription activated"
2702
+ ] }),
2703
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogDescription, { className: "text-base text-muted-foreground", children: [
2704
+ "You now have access to ",
2705
+ planName,
2706
+ ". Billing: ",
2707
+ amountLabel,
2708
+ " / ",
2709
+ billingPeriodLabel,
2710
+ "."
2711
+ ] })
2712
+ ] }),
2713
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { className: "mt-6 w-full", onClick: onClose, children: "Continue" })
2714
+ ] }) });
2715
+ };
2716
+ var useSubscriptionActions = () => {
2717
+ const { services } = usePaymentContext();
2718
+ const ensurePrice = (priceId) => {
2719
+ if (!priceId) {
2720
+ throw new Error("payments-ui: priceId is required for subscription actions");
2721
+ }
2722
+ return priceId;
2723
+ };
2724
+ const subscribeWithCard = React3.useCallback(
2725
+ async ({
2726
+ priceId,
2727
+ processor = "nmi",
2728
+ provider,
2729
+ paymentToken,
2730
+ billing
2731
+ }) => {
2732
+ const payload = {
2733
+ priceId: ensurePrice(priceId),
2734
+ paymentToken,
2735
+ processor,
2736
+ provider,
2737
+ email: billing.email,
2738
+ firstName: billing.firstName,
2739
+ lastName: billing.lastName,
2740
+ address1: billing.address1,
2741
+ city: billing.city,
2742
+ state: billing.stateRegion,
2743
+ zipCode: billing.postalCode,
2744
+ country: billing.country
2745
+ };
2746
+ return services.subscriptions.subscribe("nmi", payload);
2747
+ },
2748
+ [services]
2749
+ );
2750
+ const subscribeWithSavedMethod = React3.useCallback(
2751
+ async ({
2752
+ priceId,
2753
+ processor = "nmi",
2754
+ provider,
2755
+ paymentMethodId,
2756
+ email
2757
+ }) => {
2758
+ const payload = {
2759
+ priceId: ensurePrice(priceId),
2760
+ paymentMethodId,
2761
+ processor,
2762
+ provider,
2763
+ email
2764
+ };
2765
+ return services.subscriptions.subscribe("nmi", payload);
2766
+ },
2767
+ [services]
2768
+ );
2769
+ const subscribeWithCCBill = React3.useCallback(
2770
+ async ({
2771
+ priceId,
2772
+ email,
2773
+ firstName,
2774
+ lastName,
2775
+ zipCode,
2776
+ country,
2777
+ processor = "ccbill"
2778
+ }) => {
2779
+ const payload = {
2780
+ priceId: ensurePrice(priceId),
2781
+ email,
2782
+ firstName,
2783
+ lastName,
2784
+ zipCode,
2785
+ country,
2786
+ processor
2787
+ };
2788
+ return services.subscriptions.subscribe("ccbill", payload);
2789
+ },
2790
+ [services]
2791
+ );
2792
+ const generateFlexFormUrl = React3.useCallback(
2793
+ async ({
2794
+ priceId,
2795
+ firstName,
2796
+ lastName,
2797
+ address1,
2798
+ city,
2799
+ state,
2800
+ zipCode,
2801
+ country
2802
+ }) => {
2803
+ const payload = {
2804
+ price_id: ensurePrice(priceId),
2805
+ first_name: firstName,
2806
+ last_name: lastName,
2807
+ address1,
2808
+ city,
2809
+ state,
2810
+ zip_code: zipCode,
2811
+ country
2812
+ };
2813
+ return services.subscriptions.generateFlexFormUrl(payload);
2814
+ },
2815
+ [services]
2816
+ );
2817
+ return {
2818
+ subscribeWithCard,
2819
+ subscribeWithSavedMethod,
2820
+ subscribeWithCCBill,
2821
+ generateFlexFormUrl
2822
+ };
2823
+ };
2824
+ var SubscriptionCheckoutModal = ({
2825
+ open,
2826
+ onOpenChange,
2827
+ priceId,
2828
+ usdAmount = 0,
2829
+ planName,
2830
+ amountLabel,
2831
+ billingPeriodLabel,
2832
+ userEmail,
2833
+ provider = "mobius",
2834
+ onSuccess,
2835
+ enableSolanaPay = true
2836
+ }) => {
2837
+ const [showSuccess, setShowSuccess] = React3.useState(false);
2838
+ const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
2839
+ const handleClose = React3.useCallback(
2840
+ (nextOpen) => {
2841
+ onOpenChange(nextOpen);
2842
+ if (!nextOpen) {
2843
+ setShowSuccess(false);
2844
+ }
2845
+ },
2846
+ [onOpenChange]
2847
+ );
2848
+ const ensurePrice = () => {
2849
+ if (!priceId) {
2850
+ throw new Error("Select a plan before subscribing.");
2851
+ }
2852
+ return priceId;
2853
+ };
2854
+ const notifySuccess = (result) => {
2855
+ setShowSuccess(true);
2856
+ onSuccess?.();
2857
+ if (result && typeof window !== "undefined") {
2858
+ console.debug("[payments-ui] subscription success", result);
2859
+ }
2860
+ };
2861
+ const handleNewCardPayment = async ({ token, billing }) => {
2862
+ await subscribeWithCard({
2863
+ priceId: ensurePrice(),
2864
+ provider,
2865
+ paymentToken: token,
2866
+ billing
2867
+ });
2868
+ notifySuccess();
2869
+ };
2870
+ const handleSavedMethodPayment = async ({ paymentMethodId }) => {
2871
+ await subscribeWithSavedMethod({
2872
+ priceId: ensurePrice(),
2873
+ provider,
2874
+ paymentMethodId,
2875
+ email: userEmail ?? ""
2876
+ });
2877
+ notifySuccess();
2878
+ };
2879
+ const solanaSuccess = (result) => {
2880
+ notifySuccess(result);
2881
+ onOpenChange(false);
2882
+ };
2883
+ const summary = React3.useMemo(() => {
2884
+ if (!planName && !amountLabel) return null;
2885
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border/60 bg-muted/10 p-3 text-sm text-muted-foreground", children: [
2886
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-foreground", children: planName ?? "Selected plan" }),
2887
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
2888
+ amountLabel ?? `$${usdAmount.toFixed(2)}`,
2889
+ " ",
2890
+ billingPeriodLabel ? `/ ${billingPeriodLabel}` : ""
2891
+ ] })
2892
+ ] });
2893
+ }, [planName, amountLabel, billingPeriodLabel, usdAmount]);
2894
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2895
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-3xl", children: [
2896
+ !priceId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-center gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
2897
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-4 w-4" }),
2898
+ " Select a subscription plan to continue."
2899
+ ] }),
2900
+ /* @__PURE__ */ jsxRuntime.jsx(
2901
+ PaymentExperience,
2902
+ {
2903
+ priceId: priceId ?? "",
2904
+ usdAmount,
2905
+ checkoutSummary: summary,
2906
+ onNewCardPayment: priceId ? handleNewCardPayment : void 0,
2907
+ onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
2908
+ enableNewCard: Boolean(priceId),
2909
+ enableStoredMethods: Boolean(priceId),
2910
+ enableSolanaPay: enableSolanaPay && Boolean(priceId),
2911
+ onSolanaSuccess: solanaSuccess
2912
+ }
2913
+ )
2914
+ ] }) }),
2915
+ /* @__PURE__ */ jsxRuntime.jsx(
2916
+ SubscriptionSuccessDialog,
2917
+ {
2918
+ open: showSuccess,
2919
+ onClose: () => setShowSuccess(false),
2920
+ planName,
2921
+ amountLabel: amountLabel ?? `$${usdAmount.toFixed(2)}`,
2922
+ billingPeriodLabel
2923
+ }
2924
+ )
2925
+ ] });
2926
+ };
2688
2927
  var useTokenBalance = (tokens) => {
2689
2928
  const { publicKey } = walletAdapterReact.useWallet();
2690
2929
  const { connection } = walletAdapterReact.useConnection();
@@ -3176,113 +3415,32 @@ var usePaymentStatus = (options = {}) => {
3176
3415
  isPending: getConfirmationStatus() === "pending"
3177
3416
  };
3178
3417
  };
3179
- var useSubscriptionActions = () => {
3180
- const { services } = usePaymentContext();
3181
- const ensurePrice = (priceId) => {
3182
- if (!priceId) {
3183
- throw new Error("payments-ui: priceId is required for subscription actions");
3184
- }
3185
- return priceId;
3186
- };
3187
- const subscribeWithCard = React3.useCallback(
3188
- async ({
3189
- priceId,
3190
- processor = "nmi",
3191
- provider,
3192
- paymentToken,
3193
- billing
3194
- }) => {
3195
- const payload = {
3196
- priceId: ensurePrice(priceId),
3197
- paymentToken,
3198
- processor,
3199
- provider,
3200
- email: billing.email,
3201
- firstName: billing.firstName,
3202
- lastName: billing.lastName,
3203
- address1: billing.address1,
3204
- city: billing.city,
3205
- state: billing.stateRegion,
3206
- zipCode: billing.postalCode,
3207
- country: billing.country
3208
- };
3209
- return services.subscriptions.subscribe("nmi", payload);
3210
- },
3211
- [services]
3212
- );
3213
- const subscribeWithSavedMethod = React3.useCallback(
3214
- async ({
3215
- priceId,
3216
- processor = "nmi",
3217
- provider,
3218
- paymentMethodId,
3219
- email
3220
- }) => {
3221
- const payload = {
3222
- priceId: ensurePrice(priceId),
3223
- paymentMethodId,
3224
- processor,
3225
- provider,
3226
- email
3227
- };
3228
- return services.subscriptions.subscribe("nmi", payload);
3229
- },
3230
- [services]
3231
- );
3232
- const subscribeWithCCBill = React3.useCallback(
3233
- async ({
3234
- priceId,
3235
- email,
3236
- firstName,
3237
- lastName,
3238
- zipCode,
3239
- country,
3240
- processor = "ccbill"
3241
- }) => {
3242
- const payload = {
3243
- priceId: ensurePrice(priceId),
3244
- email,
3245
- firstName,
3246
- lastName,
3247
- zipCode,
3248
- country,
3249
- processor
3250
- };
3251
- return services.subscriptions.subscribe("ccbill", payload);
3252
- },
3253
- [services]
3254
- );
3255
- const generateFlexFormUrl = React3.useCallback(
3256
- async ({
3257
- priceId,
3258
- firstName,
3259
- lastName,
3260
- address1,
3261
- city,
3262
- state,
3263
- zipCode,
3264
- country
3265
- }) => {
3266
- const payload = {
3267
- price_id: ensurePrice(priceId),
3268
- first_name: firstName,
3269
- last_name: lastName,
3270
- address1,
3271
- city,
3272
- state,
3273
- zip_code: zipCode,
3274
- country
3275
- };
3276
- return services.subscriptions.generateFlexFormUrl(payload);
3418
+ var useAlternativePaymentProvider = () => {
3419
+ const [isLoading, setIsLoading] = React3.useState(false);
3420
+ const [error, setError] = React3.useState(null);
3421
+ const { generateFlexFormUrl } = useSubscriptionActions();
3422
+ const openFlexForm = React3.useCallback(
3423
+ async (payload) => {
3424
+ setIsLoading(true);
3425
+ setError(null);
3426
+ try {
3427
+ const response = await generateFlexFormUrl(payload);
3428
+ if (response?.iframe_url) {
3429
+ window.location.href = response.iframe_url;
3430
+ } else {
3431
+ throw new Error("Unable to launch payment provider.");
3432
+ }
3433
+ } catch (err) {
3434
+ const message = err instanceof Error ? err.message : "Failed to open payment provider.";
3435
+ setError(message);
3436
+ console.error("[payments-ui] failed to open alternative payment provider", err);
3437
+ } finally {
3438
+ setIsLoading(false);
3439
+ }
3277
3440
  },
3278
- [services]
3441
+ [generateFlexFormUrl]
3279
3442
  );
3280
- return {
3281
- subscribeWithCard,
3282
- subscribeWithSavedMethod,
3283
- subscribeWithCCBill,
3284
- generateFlexFormUrl
3285
- };
3443
+ return { openFlexForm, isLoading, error };
3286
3444
  };
3287
3445
 
3288
3446
  exports.CardDetailsForm = CardDetailsForm;
@@ -3294,10 +3452,13 @@ exports.PaymentProvider = PaymentProvider;
3294
3452
  exports.SolanaPaymentSelector = SolanaPaymentSelector;
3295
3453
  exports.SolanaPaymentService = SolanaPaymentService;
3296
3454
  exports.StoredPaymentMethods = StoredPaymentMethods;
3455
+ exports.SubscriptionCheckoutModal = SubscriptionCheckoutModal;
3297
3456
  exports.SubscriptionService = SubscriptionService;
3457
+ exports.SubscriptionSuccessDialog = SubscriptionSuccessDialog;
3298
3458
  exports.TokenCatalog = TokenCatalog;
3299
3459
  exports.WalletGateway = WalletGateway;
3300
3460
  exports.createPaymentStore = createPaymentStore;
3461
+ exports.useAlternativePaymentProvider = useAlternativePaymentProvider;
3301
3462
  exports.useDirectWalletPayment = useDirectWalletPayment;
3302
3463
  exports.usePaymentContext = usePaymentContext;
3303
3464
  exports.usePaymentMethodService = usePaymentMethodService;