@windrun-huaiin/third-ui 31.3.7 → 31.4.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 (31) hide show
  1. package/dist/main/credit/credit-nav-button.d.ts +3 -2
  2. package/dist/main/credit/credit-nav-button.js +7 -9
  3. package/dist/main/credit/credit-nav-button.mjs +5 -7
  4. package/dist/main/credit/credit-overview-nav-client.d.ts +7 -2
  5. package/dist/main/credit/credit-overview-nav-client.js +2 -2
  6. package/dist/main/credit/credit-overview-nav-client.mjs +2 -2
  7. package/dist/main/credit/index.d.ts +1 -1
  8. package/dist/main/credit/types.d.ts +1 -0
  9. package/dist/main/money-price/index.d.ts +2 -0
  10. package/dist/main/money-price/index.js +4 -0
  11. package/dist/main/money-price/index.mjs +1 -0
  12. package/dist/main/money-price/money-price-interactive.d.ts +1 -1
  13. package/dist/main/money-price/money-price-interactive.js +7 -5
  14. package/dist/main/money-price/money-price-interactive.mjs +7 -5
  15. package/dist/main/money-price/money-price-types.d.ts +2 -0
  16. package/dist/main/money-price/money-price.d.ts +1 -1
  17. package/dist/main/money-price/money-price.js +2 -2
  18. package/dist/main/money-price/money-price.mjs +2 -2
  19. package/dist/main/money-price/pricing-modal.d.ts +33 -0
  20. package/dist/main/money-price/pricing-modal.js +109 -0
  21. package/dist/main/money-price/pricing-modal.mjs +105 -0
  22. package/package.json +3 -3
  23. package/src/main/credit/credit-nav-button.tsx +15 -56
  24. package/src/main/credit/credit-overview-nav-client.tsx +8 -1
  25. package/src/main/credit/index.ts +1 -0
  26. package/src/main/credit/types.ts +1 -0
  27. package/src/main/money-price/index.ts +10 -0
  28. package/src/main/money-price/money-price-interactive.tsx +41 -31
  29. package/src/main/money-price/money-price-types.ts +2 -0
  30. package/src/main/money-price/money-price.tsx +2 -0
  31. package/src/main/money-price/pricing-modal.tsx +283 -0
@@ -1,12 +1,13 @@
1
1
  import type { MoneyPriceData } from '../money-price/money-price-types';
2
- import type { CreditPricingContext, PricingModalMode } from './types';
2
+ import type { CreditPricingContext, MobileBillingSwitchBehavior, PricingModalMode } from './types';
3
3
  interface CreditNavButtonProps {
4
4
  locale: string;
5
5
  totalBalance: number;
6
6
  totalLabel: string;
7
+ mobileBillingSwitchBehavior?: MobileBillingSwitchBehavior;
7
8
  children: React.ReactNode;
8
9
  }
9
- export declare function CreditNavButton({ locale, totalBalance, totalLabel, children, }: CreditNavButtonProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function CreditNavButton({ locale, totalBalance, totalLabel, mobileBillingSwitchBehavior, children, }: CreditNavButtonProps): import("react/jsx-runtime").JSX.Element;
10
11
  interface CreditNavPopoverContextValue {
11
12
  close: () => void;
12
13
  isMobile: boolean;
@@ -4,20 +4,18 @@
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var utils = require('@windrun-huaiin/lib/utils');
6
6
  var icons = require('@windrun-huaiin/base-ui/icons');
7
- var lib = require('@windrun-huaiin/base-ui/lib');
8
7
  var ui = require('@windrun-huaiin/base-ui/ui');
9
8
  var React = require('react');
10
- var moneyPriceInteractive = require('../money-price/money-price-interactive.js');
11
9
  var moneyPriceConfigUtil = require('../money-price/money-price-config-util.js');
12
- var dialogStyles = require('../alert-dialog/dialog-styles.js');
10
+ var pricingModal = require('../money-price/pricing-modal.js');
13
11
 
14
- function CreditNavButton({ locale, totalBalance, totalLabel, children, }) {
12
+ function CreditNavButton({ locale, totalBalance, totalLabel, mobileBillingSwitchBehavior, children, }) {
15
13
  const [open, setOpen] = React.useState(false);
16
14
  const [isMobile, setIsMobile] = React.useState(false);
17
15
  const triggerRef = React.useRef(null);
18
16
  const contentRef = React.useRef(null);
19
17
  const closeMenu = React.useCallback(() => setOpen(false), []);
20
- const [pricingModal, setPricingModal] = React.useState({
18
+ const [pricingModal$1, setPricingModal] = React.useState({
21
19
  open: false,
22
20
  mode: 'subscription',
23
21
  });
@@ -108,13 +106,13 @@ function CreditNavButton({ locale, totalBalance, totalLabel, children, }) {
108
106
  openPricingModal,
109
107
  closePricingModal,
110
108
  }), [closeMenu, isMobile, openPricingModal, closePricingModal]);
111
- const isOnetimeModal = pricingModal.mode === 'onetime';
109
+ const isOnetimeModal = pricingModal$1.mode === 'onetime';
112
110
  const modalInitialBillingType = React.useMemo(() => {
113
111
  var _a, _b;
114
112
  if (isOnetimeModal) {
115
113
  return 'onetime';
116
114
  }
117
- const pricingContext = pricingModal.pricingContext;
115
+ const pricingContext = pricingModal$1.pricingContext;
118
116
  const priceId = (_b = (_a = pricingContext === null || pricingContext === void 0 ? void 0 : pricingContext.initUserContext) === null || _a === void 0 ? void 0 : _a.xSubscription) === null || _b === void 0 ? void 0 : _b.priceId;
119
117
  if (!pricingContext || !priceId) {
120
118
  return undefined;
@@ -129,8 +127,8 @@ function CreditNavButton({ locale, totalBalance, totalLabel, children, }) {
129
127
  }
130
128
  }
131
129
  return undefined;
132
- }, [isOnetimeModal, pricingModal.pricingContext]);
133
- return (jsxRuntime.jsxs(CreditNavPopoverContext.Provider, { value: contextValue, children: [jsxRuntime.jsxs(ui.DropdownMenu, { modal: false, open: open, onOpenChange: setOpen, children: [jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: jsxRuntime.jsxs("button", { type: "button", "aria-label": `${formattedBalance} ${totalLabel}`, className: utils.cn('group relative mx-2 sm:mx-1 inline-flex items-center gap-2 overflow-hidden rounded-full border border-slate-200 bg-white pl-2 pr-4 py-1.5 text-sm font-semibold text-slate-700 shadow-sm transition-all duration-200 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100', 'hover:-translate-y-0.5 hover:scale-[1.02] hover:border-transparent hover:text-white hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-slate-400 dark:focus-visible:ring-slate-500'), ref: triggerRef, children: [jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-200 group-hover:opacity-100 group-focus-visible:opacity-100 bg-linear-to-bl from-indigo-200/60 via-indigo-400/90 to-purple-200/50 dark:from-indigo-300/20 dark:via-slate-400 dark:to-slate-500/50", "aria-hidden": "true" }), jsxRuntime.jsx("span", { className: "relative z-10 flex h-6 w-6 items-center justify-center rounded-full bg-slate-100 text-slate-600 transition-transform duration-200 group-hover:scale-110 group-hover:bg-white/20 group-hover:text-white dark:bg-slate-800 dark:text-slate-200 dark:group-hover:bg-white/20 dark:group-hover:text-white", children: jsxRuntime.jsx(icons.GemIcon, { className: "h-3.5 w-3.5" }) }), jsxRuntime.jsxs("span", { className: "relative z-10 flex items-center", children: [jsxRuntime.jsx("span", { className: "text-base font-semibold leading-none", children: formattedBalance }), jsxRuntime.jsx("span", { className: "sr-only", children: ` ${totalLabel}` })] })] }) }), jsxRuntime.jsx(ui.DropdownMenuContent, { forceMount: true, sideOffset: 12, align: "end", className: "z-50 border-0 bg-transparent p-0 shadow-none mx-4 sm:mx-2 md:mx-1", children: jsxRuntime.jsx("div", { className: "w-[90vw] max-w-[90vw] max-h-[80vh] overflow-y-auto overflow-x-hidden rounded-3xl bg-transparent sm:w-[410px] sm:max-h-[90vh] sm:max-w-[95vw]", ref: contentRef, children: children }) })] }), pricingModal.modalMoneyPriceData && pricingModal.pricingContext ? (jsxRuntime.jsx(ui.AlertDialog, { open: pricingModal.open, onOpenChange: (open) => setPricingModal((prev) => (Object.assign(Object.assign({}, prev), { open }))), children: jsxRuntime.jsxs(ui.AlertDialogContent, { className: utils.cn('mt-5 sm:mt-6 md:mt-10 lg:mt-15 w-[95vw] max-w-[1200px] overflow-hidden border border-slate-200 p-0 shadow-[0_32px_90px_rgba(15,23,42,0.25)] ring-1 ring-black/5 dark:border-white/12 dark:shadow-[0_40px_120px_rgba(0,0,0,0.6)] dark:ring-white/10', lib.themeMainBgColor), overlayClassName: dialogStyles.dialogThemedOverlayClass, children: [jsxRuntime.jsxs(ui.AlertDialogHeader, { className: "flex flex-row items-center justify-between border-b border-slate-200 px-6 pt-4 pb-1 dark:border-slate-800", children: [jsxRuntime.jsx(ui.AlertDialogTitle, { asChild: true, children: jsxRuntime.jsxs("div", { className: "flex flex-wrap items-baseline gap-3 text-slate-900 dark:text-white", children: [jsxRuntime.jsx("span", { className: "text-2xl font-semibold leading-tight", children: pricingModal.modalMoneyPriceData.title }), pricingModal.modalMoneyPriceData.subtitle ? (jsxRuntime.jsx("span", { className: "text-sm font-medium text-slate-500 dark:text-slate-300", children: pricingModal.modalMoneyPriceData.subtitle })) : null] }) }), jsxRuntime.jsx("button", { type: "button", className: "rounded-full p-2 text-gray-400 transition hover:bg-gray-400 hover:text-gray-400 dark:text-white/80 dark:hover:bg-white/80 dark:hover:text-white/80", onClick: closePricingModal, children: jsxRuntime.jsx(icons.XIcon, { className: "h-6 w-6" }) })] }), jsxRuntime.jsx("div", { className: "max-h-[60vh] sm:max-h-[80vh] overflow-y-auto px-4 pt-2 pb-6", children: jsxRuntime.jsx("div", { className: "mx-auto w-full", children: jsxRuntime.jsx(moneyPriceInteractive.MoneyPriceInteractive, { data: pricingModal.modalMoneyPriceData, config: pricingModal.pricingContext.moneyPriceConfig, checkoutApiEndpoint: pricingModal.pricingContext.checkoutApiEndpoint, customerPortalApiEndpoint: pricingModal.pricingContext.customerPortalApiEndpoint, enableSubscriptionUpgrade: pricingModal.pricingContext.enableSubscriptionUpgrade, initialBillingType: modalInitialBillingType, disableAutoDetectBilling: isOnetimeModal, initUserContext: pricingModal.pricingContext.initUserContext }, pricingModal.mode) }) })] }) })) : null] }));
130
+ }, [isOnetimeModal, pricingModal$1.pricingContext]);
131
+ return (jsxRuntime.jsxs(CreditNavPopoverContext.Provider, { value: contextValue, children: [jsxRuntime.jsxs(ui.DropdownMenu, { modal: false, open: open, onOpenChange: setOpen, children: [jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: jsxRuntime.jsxs("button", { type: "button", "aria-label": `${formattedBalance} ${totalLabel}`, className: utils.cn('group relative mx-2 sm:mx-1 inline-flex items-center gap-2 overflow-hidden rounded-full border border-slate-200 bg-white pl-2 pr-4 py-1.5 text-sm font-semibold text-slate-700 shadow-sm transition-all duration-200 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100', 'hover:-translate-y-0.5 hover:scale-[1.02] hover:border-transparent hover:text-white hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-slate-400 dark:focus-visible:ring-slate-500'), ref: triggerRef, children: [jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-200 group-hover:opacity-100 group-focus-visible:opacity-100 bg-linear-to-bl from-indigo-200/60 via-indigo-400/90 to-purple-200/50 dark:from-indigo-300/20 dark:via-slate-400 dark:to-slate-500/50", "aria-hidden": "true" }), jsxRuntime.jsx("span", { className: "relative z-10 flex h-6 w-6 items-center justify-center rounded-full bg-slate-100 text-slate-600 transition-transform duration-200 group-hover:scale-110 group-hover:bg-white/20 group-hover:text-white dark:bg-slate-800 dark:text-slate-200 dark:group-hover:bg-white/20 dark:group-hover:text-white", children: jsxRuntime.jsx(icons.GemIcon, { className: "h-3.5 w-3.5" }) }), jsxRuntime.jsxs("span", { className: "relative z-10 flex items-center", children: [jsxRuntime.jsx("span", { className: "text-base font-semibold leading-none", children: formattedBalance }), jsxRuntime.jsx("span", { className: "sr-only", children: ` ${totalLabel}` })] })] }) }), jsxRuntime.jsx(ui.DropdownMenuContent, { forceMount: true, sideOffset: 12, align: "end", className: "z-50 border-0 bg-transparent p-0 shadow-none mx-4 sm:mx-2 md:mx-1", children: jsxRuntime.jsx("div", { className: "w-[90vw] max-w-[90vw] max-h-[80vh] overflow-y-auto overflow-x-hidden rounded-3xl bg-transparent sm:w-[410px] sm:max-h-[90vh] sm:max-w-[95vw]", ref: contentRef, children: children }) })] }), pricingModal$1.modalMoneyPriceData && pricingModal$1.pricingContext ? (jsxRuntime.jsx(pricingModal.PricingModal, { open: pricingModal$1.open, onOpenChange: (open) => setPricingModal((prev) => (Object.assign(Object.assign({}, prev), { open }))), data: pricingModal$1.modalMoneyPriceData, config: pricingModal$1.pricingContext.moneyPriceConfig, checkoutApiEndpoint: pricingModal$1.pricingContext.checkoutApiEndpoint, customerPortalApiEndpoint: pricingModal$1.pricingContext.customerPortalApiEndpoint, mobileBillingSwitchBehavior: mobileBillingSwitchBehavior, enableSubscriptionUpgrade: pricingModal$1.pricingContext.enableSubscriptionUpgrade, billingType: modalInitialBillingType, initUserContext: pricingModal$1.pricingContext.initUserContext })) : null] }));
134
132
  }
135
133
  const CreditNavPopoverContext = React.createContext(null);
136
134
  function useCreditNavPopover() {
@@ -1,15 +1,13 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { cn } from '@windrun-huaiin/lib/utils';
4
- import { GemIcon, XIcon } from '@windrun-huaiin/base-ui/icons';
5
- import { themeMainBgColor } from '@windrun-huaiin/base-ui/lib';
6
- import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle } from '@windrun-huaiin/base-ui/ui';
4
+ import { GemIcon } from '@windrun-huaiin/base-ui/icons';
5
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent } from '@windrun-huaiin/base-ui/ui';
7
6
  import { createContext, useState, useRef, useCallback, useMemo, useEffect, useContext } from 'react';
8
- import { MoneyPriceInteractive } from '../money-price/money-price-interactive.mjs';
9
7
  import { getActiveProviderConfigUtil } from '../money-price/money-price-config-util.mjs';
10
- import { dialogThemedOverlayClass } from '../alert-dialog/dialog-styles.mjs';
8
+ import { PricingModal } from '../money-price/pricing-modal.mjs';
11
9
 
12
- function CreditNavButton({ locale, totalBalance, totalLabel, children, }) {
10
+ function CreditNavButton({ locale, totalBalance, totalLabel, mobileBillingSwitchBehavior, children, }) {
13
11
  const [open, setOpen] = useState(false);
14
12
  const [isMobile, setIsMobile] = useState(false);
15
13
  const triggerRef = useRef(null);
@@ -128,7 +126,7 @@ function CreditNavButton({ locale, totalBalance, totalLabel, children, }) {
128
126
  }
129
127
  return undefined;
130
128
  }, [isOnetimeModal, pricingModal.pricingContext]);
131
- return (jsxs(CreditNavPopoverContext.Provider, { value: contextValue, children: [jsxs(DropdownMenu, { modal: false, open: open, onOpenChange: setOpen, children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs("button", { type: "button", "aria-label": `${formattedBalance} ${totalLabel}`, className: cn('group relative mx-2 sm:mx-1 inline-flex items-center gap-2 overflow-hidden rounded-full border border-slate-200 bg-white pl-2 pr-4 py-1.5 text-sm font-semibold text-slate-700 shadow-sm transition-all duration-200 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100', 'hover:-translate-y-0.5 hover:scale-[1.02] hover:border-transparent hover:text-white hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-slate-400 dark:focus-visible:ring-slate-500'), ref: triggerRef, children: [jsx("span", { className: "pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-200 group-hover:opacity-100 group-focus-visible:opacity-100 bg-linear-to-bl from-indigo-200/60 via-indigo-400/90 to-purple-200/50 dark:from-indigo-300/20 dark:via-slate-400 dark:to-slate-500/50", "aria-hidden": "true" }), jsx("span", { className: "relative z-10 flex h-6 w-6 items-center justify-center rounded-full bg-slate-100 text-slate-600 transition-transform duration-200 group-hover:scale-110 group-hover:bg-white/20 group-hover:text-white dark:bg-slate-800 dark:text-slate-200 dark:group-hover:bg-white/20 dark:group-hover:text-white", children: jsx(GemIcon, { className: "h-3.5 w-3.5" }) }), jsxs("span", { className: "relative z-10 flex items-center", children: [jsx("span", { className: "text-base font-semibold leading-none", children: formattedBalance }), jsx("span", { className: "sr-only", children: ` ${totalLabel}` })] })] }) }), jsx(DropdownMenuContent, { forceMount: true, sideOffset: 12, align: "end", className: "z-50 border-0 bg-transparent p-0 shadow-none mx-4 sm:mx-2 md:mx-1", children: jsx("div", { className: "w-[90vw] max-w-[90vw] max-h-[80vh] overflow-y-auto overflow-x-hidden rounded-3xl bg-transparent sm:w-[410px] sm:max-h-[90vh] sm:max-w-[95vw]", ref: contentRef, children: children }) })] }), pricingModal.modalMoneyPriceData && pricingModal.pricingContext ? (jsx(AlertDialog, { open: pricingModal.open, onOpenChange: (open) => setPricingModal((prev) => (Object.assign(Object.assign({}, prev), { open }))), children: jsxs(AlertDialogContent, { className: cn('mt-5 sm:mt-6 md:mt-10 lg:mt-15 w-[95vw] max-w-[1200px] overflow-hidden border border-slate-200 p-0 shadow-[0_32px_90px_rgba(15,23,42,0.25)] ring-1 ring-black/5 dark:border-white/12 dark:shadow-[0_40px_120px_rgba(0,0,0,0.6)] dark:ring-white/10', themeMainBgColor), overlayClassName: dialogThemedOverlayClass, children: [jsxs(AlertDialogHeader, { className: "flex flex-row items-center justify-between border-b border-slate-200 px-6 pt-4 pb-1 dark:border-slate-800", children: [jsx(AlertDialogTitle, { asChild: true, children: jsxs("div", { className: "flex flex-wrap items-baseline gap-3 text-slate-900 dark:text-white", children: [jsx("span", { className: "text-2xl font-semibold leading-tight", children: pricingModal.modalMoneyPriceData.title }), pricingModal.modalMoneyPriceData.subtitle ? (jsx("span", { className: "text-sm font-medium text-slate-500 dark:text-slate-300", children: pricingModal.modalMoneyPriceData.subtitle })) : null] }) }), jsx("button", { type: "button", className: "rounded-full p-2 text-gray-400 transition hover:bg-gray-400 hover:text-gray-400 dark:text-white/80 dark:hover:bg-white/80 dark:hover:text-white/80", onClick: closePricingModal, children: jsx(XIcon, { className: "h-6 w-6" }) })] }), jsx("div", { className: "max-h-[60vh] sm:max-h-[80vh] overflow-y-auto px-4 pt-2 pb-6", children: jsx("div", { className: "mx-auto w-full", children: jsx(MoneyPriceInteractive, { data: pricingModal.modalMoneyPriceData, config: pricingModal.pricingContext.moneyPriceConfig, checkoutApiEndpoint: pricingModal.pricingContext.checkoutApiEndpoint, customerPortalApiEndpoint: pricingModal.pricingContext.customerPortalApiEndpoint, enableSubscriptionUpgrade: pricingModal.pricingContext.enableSubscriptionUpgrade, initialBillingType: modalInitialBillingType, disableAutoDetectBilling: isOnetimeModal, initUserContext: pricingModal.pricingContext.initUserContext }, pricingModal.mode) }) })] }) })) : null] }));
129
+ return (jsxs(CreditNavPopoverContext.Provider, { value: contextValue, children: [jsxs(DropdownMenu, { modal: false, open: open, onOpenChange: setOpen, children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs("button", { type: "button", "aria-label": `${formattedBalance} ${totalLabel}`, className: cn('group relative mx-2 sm:mx-1 inline-flex items-center gap-2 overflow-hidden rounded-full border border-slate-200 bg-white pl-2 pr-4 py-1.5 text-sm font-semibold text-slate-700 shadow-sm transition-all duration-200 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100', 'hover:-translate-y-0.5 hover:scale-[1.02] hover:border-transparent hover:text-white hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-slate-400 dark:focus-visible:ring-slate-500'), ref: triggerRef, children: [jsx("span", { className: "pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-200 group-hover:opacity-100 group-focus-visible:opacity-100 bg-linear-to-bl from-indigo-200/60 via-indigo-400/90 to-purple-200/50 dark:from-indigo-300/20 dark:via-slate-400 dark:to-slate-500/50", "aria-hidden": "true" }), jsx("span", { className: "relative z-10 flex h-6 w-6 items-center justify-center rounded-full bg-slate-100 text-slate-600 transition-transform duration-200 group-hover:scale-110 group-hover:bg-white/20 group-hover:text-white dark:bg-slate-800 dark:text-slate-200 dark:group-hover:bg-white/20 dark:group-hover:text-white", children: jsx(GemIcon, { className: "h-3.5 w-3.5" }) }), jsxs("span", { className: "relative z-10 flex items-center", children: [jsx("span", { className: "text-base font-semibold leading-none", children: formattedBalance }), jsx("span", { className: "sr-only", children: ` ${totalLabel}` })] })] }) }), jsx(DropdownMenuContent, { forceMount: true, sideOffset: 12, align: "end", className: "z-50 border-0 bg-transparent p-0 shadow-none mx-4 sm:mx-2 md:mx-1", children: jsx("div", { className: "w-[90vw] max-w-[90vw] max-h-[80vh] overflow-y-auto overflow-x-hidden rounded-3xl bg-transparent sm:w-[410px] sm:max-h-[90vh] sm:max-w-[95vw]", ref: contentRef, children: children }) })] }), pricingModal.modalMoneyPriceData && pricingModal.pricingContext ? (jsx(PricingModal, { open: pricingModal.open, onOpenChange: (open) => setPricingModal((prev) => (Object.assign(Object.assign({}, prev), { open }))), data: pricingModal.modalMoneyPriceData, config: pricingModal.pricingContext.moneyPriceConfig, checkoutApiEndpoint: pricingModal.pricingContext.checkoutApiEndpoint, customerPortalApiEndpoint: pricingModal.pricingContext.customerPortalApiEndpoint, mobileBillingSwitchBehavior: mobileBillingSwitchBehavior, enableSubscriptionUpgrade: pricingModal.pricingContext.enableSubscriptionUpgrade, billingType: modalInitialBillingType, initUserContext: pricingModal.pricingContext.initUserContext })) : null] }));
132
130
  }
133
131
  const CreditNavPopoverContext = createContext(null);
134
132
  function useCreditNavPopover() {
@@ -1,5 +1,5 @@
1
1
  import { type CreditOverviewTranslations } from './credit-overview-client';
2
- import type { CreditOverviewData } from './types';
2
+ import type { CreditOverviewData, MobileBillingSwitchBehavior } from './types';
3
3
  export declare const DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = "windrun-huaiin:credit-overview:refresh";
4
4
  export interface CreditOverviewPayload {
5
5
  data: CreditOverviewData;
@@ -14,6 +14,11 @@ export interface CreditOverviewNavClientProps {
14
14
  * Defaults are handled by the API/payload builder when omitted.
15
15
  */
16
16
  enabledBillingTypes?: string[];
17
+ /**
18
+ * Mobile behavior for the pricing modal billing switch.
19
+ * Default: 'sticky'.
20
+ */
21
+ mobileBillingSwitchBehavior?: MobileBillingSwitchBehavior;
17
22
  /**
18
23
  * Browser event names that should trigger credit overview reload.
19
24
  * Business apps can dispatch these events after credit balance changes.
@@ -29,4 +34,4 @@ export interface CreditOverviewNavClientProps {
29
34
  refreshDebounceMs?: number;
30
35
  }
31
36
  export declare function dispatchCreditOverviewRefresh(eventName?: string): void;
32
- export declare function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, refreshEvents, refreshDebounceMs, }: CreditOverviewNavClientProps): import("react/jsx-runtime").JSX.Element | null;
37
+ export declare function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, mobileBillingSwitchBehavior, refreshEvents, refreshDebounceMs, }: CreditOverviewNavClientProps): import("react/jsx-runtime").JSX.Element | null;
@@ -43,7 +43,7 @@ function dispatchCreditOverviewRefresh(eventName = DEFAULT_CREDIT_OVERVIEW_REFRE
43
43
  }
44
44
  window.dispatchEvent(new CustomEvent(eventName));
45
45
  }
46
- function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, refreshEvents, refreshDebounceMs = 300, }) {
46
+ function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, mobileBillingSwitchBehavior, refreshEvents, refreshDebounceMs = 300, }) {
47
47
  const { isLoaded, isSignedIn, userId } = nextjs.useAuth();
48
48
  const [payload, setPayload] = React.useState(null);
49
49
  const abortControllerRef = React.useRef(null);
@@ -135,7 +135,7 @@ function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, refres
135
135
  if (!payload) {
136
136
  return null;
137
137
  }
138
- return (jsxRuntime.jsx(creditNavButton.CreditNavButton, { locale: locale, totalBalance: payload.data.totalBalance, totalLabel: payload.totalLabel, children: jsxRuntime.jsx(creditOverviewClient.CreditOverviewClient, { locale: locale, data: payload.data, translations: payload.translations }) }));
138
+ return (jsxRuntime.jsx(creditNavButton.CreditNavButton, { locale: locale, totalBalance: payload.data.totalBalance, totalLabel: payload.totalLabel, mobileBillingSwitchBehavior: mobileBillingSwitchBehavior, children: jsxRuntime.jsx(creditOverviewClient.CreditOverviewClient, { locale: locale, data: payload.data, translations: payload.translations }) }));
139
139
  }
140
140
 
141
141
  exports.CreditOverviewNavClient = CreditOverviewNavClient;
@@ -41,7 +41,7 @@ function dispatchCreditOverviewRefresh(eventName = DEFAULT_CREDIT_OVERVIEW_REFRE
41
41
  }
42
42
  window.dispatchEvent(new CustomEvent(eventName));
43
43
  }
44
- function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, refreshEvents, refreshDebounceMs = 300, }) {
44
+ function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, mobileBillingSwitchBehavior, refreshEvents, refreshDebounceMs = 300, }) {
45
45
  const { isLoaded, isSignedIn, userId } = useAuth();
46
46
  const [payload, setPayload] = useState(null);
47
47
  const abortControllerRef = useRef(null);
@@ -133,7 +133,7 @@ function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, refres
133
133
  if (!payload) {
134
134
  return null;
135
135
  }
136
- return (jsx(CreditNavButton, { locale: locale, totalBalance: payload.data.totalBalance, totalLabel: payload.totalLabel, children: jsx(CreditOverviewClient, { locale: locale, data: payload.data, translations: payload.translations }) }));
136
+ return (jsx(CreditNavButton, { locale: locale, totalBalance: payload.data.totalBalance, totalLabel: payload.totalLabel, mobileBillingSwitchBehavior: mobileBillingSwitchBehavior, children: jsx(CreditOverviewClient, { locale: locale, data: payload.data, translations: payload.translations }) }));
137
137
  }
138
138
 
139
139
  export { CreditOverviewNavClient, DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT, dispatchCreditOverviewRefresh };
@@ -3,4 +3,4 @@ export { CreditOverviewNavClient, DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT, dispatc
3
3
  export { CreditNavButton } from './credit-nav-button';
4
4
  export type { CreditOverviewTranslations } from './credit-overview-client';
5
5
  export type { CreditOverviewNavClientProps, CreditOverviewPayload, } from './credit-overview-nav-client';
6
- export type { CreditOverviewData, CreditBucket, CreditBucketStatus, SubscriptionInfo, } from './types';
6
+ export type { CreditOverviewData, CreditBucket, CreditBucketStatus, MobileBillingSwitchBehavior, SubscriptionInfo, } from './types';
@@ -1,5 +1,6 @@
1
1
  import type { InitUserContext, MoneyPriceConfig, MoneyPriceData } from '../money-price/money-price-types';
2
2
  export type PricingModalMode = 'subscription' | 'onetime';
3
+ export type MobileBillingSwitchBehavior = 'sticky' | 'static';
3
4
  export type CreditActionConfig = CreditModalAction | CreditRedirectAction | CreditAuthAction | CreditCustomAction;
4
5
  export interface CreditModalAction {
5
6
  kind: 'modal';
@@ -1,4 +1,6 @@
1
1
  export { MoneyPriceInteractive } from './money-price-interactive';
2
2
  export { MoneyPriceButton } from './money-price-button';
3
+ export { PricingModal, PricingModalProvider, usePricingModal, } from './pricing-modal';
3
4
  export type { MoneyPriceConfig, MoneyPriceData, MoneyPriceAnimeTone, MoneyPriceStrictDiffAnime, InitUserContext, MoneyPriceInteractiveProps, MoneyPriceButtonProps, PaymentProvider, PaymentProviderConfig, EnhancePricePlan, SubscriptionProductConfig, CreditPackProductConfig, UserContext, } from './money-price-types';
5
+ export type { OpenPricingModalOptions, PricingModalProps, PricingModalProviderProps, } from './pricing-modal';
4
6
  export { UserState } from './money-price-types';
@@ -3,12 +3,16 @@
3
3
 
4
4
  var moneyPriceInteractive = require('./money-price-interactive.js');
5
5
  var moneyPriceButton = require('./money-price-button.js');
6
+ var pricingModal = require('./pricing-modal.js');
6
7
  var moneyPriceTypes = require('./money-price-types.js');
7
8
 
8
9
 
9
10
 
10
11
  exports.MoneyPriceInteractive = moneyPriceInteractive.MoneyPriceInteractive;
11
12
  exports.MoneyPriceButton = moneyPriceButton.MoneyPriceButton;
13
+ exports.PricingModal = pricingModal.PricingModal;
14
+ exports.PricingModalProvider = pricingModal.PricingModalProvider;
15
+ exports.usePricingModal = pricingModal.usePricingModal;
12
16
  Object.defineProperty(exports, "UserState", {
13
17
  enumerable: true,
14
18
  get: function () { return moneyPriceTypes.UserState; }
@@ -1,4 +1,5 @@
1
1
  "use client";
2
2
  export { MoneyPriceInteractive } from './money-price-interactive.mjs';
3
3
  export { MoneyPriceButton } from './money-price-button.mjs';
4
+ export { PricingModal, PricingModalProvider, usePricingModal } from './pricing-modal.mjs';
4
5
  export { UserState } from './money-price-types.mjs';
@@ -1,2 +1,2 @@
1
1
  import { type MoneyPriceInteractiveProps } from './money-price-types';
2
- export declare function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal, enabledBillingTypes, enableSubscriptionUpgrade, initialBillingType, disableAutoDetectBilling, initUserContext, isInitLoading, }: MoneyPriceInteractiveProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal, enabledBillingTypes, mobileBillingSwitchBehavior, enableSubscriptionUpgrade, initialBillingType, disableAutoDetectBilling, initUserContext, isInitLoading, }: MoneyPriceInteractiveProps): import("react/jsx-runtime").JSX.Element;
@@ -17,7 +17,7 @@ require('animejs');
17
17
  require('../anime/anime-404-page.js');
18
18
 
19
19
  const PLAN_KEYS = ['F1', 'P2', 'U3'];
20
- function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, enabledBillingTypes, enableSubscriptionUpgrade = true, initialBillingType, disableAutoDetectBilling = false, initUserContext, isInitLoading = false, }) {
20
+ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, enabledBillingTypes, mobileBillingSwitchBehavior = 'static', enableSubscriptionUpgrade = true, initialBillingType, disableAutoDetectBilling = false, initUserContext, isInitLoading = false, }) {
21
21
  var _a, _b, _c, _d, _e, _f;
22
22
  const { redirectToSignIn, redirectToSignUp, user: clerkUser, openSignUp } = nextjs.useClerk();
23
23
  const router = navigation.useRouter();
@@ -37,6 +37,7 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
37
37
  return acc;
38
38
  }, {});
39
39
  }, [billingOptions]);
40
+ const showBillingSwitch = billingOptions.length > 1;
40
41
  const defaultBilling = React.useMemo(() => {
41
42
  var _a;
42
43
  const defaultKey = data.billingSwitch.defaultKey;
@@ -309,15 +310,16 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
309
310
  return null;
310
311
  return selectedBillingOption.discountText.replace('{percent}', String(discountPercent));
311
312
  }, [selectedBillingOption, providerConfig, billingType]);
312
- // Configure the mobile floating style for BillingTypeButton.
313
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "flex justify-center mb-6 max-md:sticky max-md:top-30 max-md:z-30 max-md:py-2 max-md:bg-transparent", children: jsxRuntime.jsx("div", { className: "inline-flex bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-full px-2 py-2 sm:px-3 sm:py-3 max-md:w-full max-md:max-w-[340px] max-md:mx-auto shadow-sm", "data-billing-switch": true, children: billingOptions.map(option => {
313
+ // Configure the mobile behavior for BillingTypeButton.
314
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [showBillingSwitch ? (jsxRuntime.jsx("div", { className: utils.cn('mb-6 flex justify-center', mobileBillingSwitchBehavior === 'sticky' &&
315
+ 'max-md:sticky max-md:top-2 max-md:z-30 max-md:py-2 max-md:bg-transparent'), children: jsxRuntime.jsx("div", { className: "inline-flex max-w-[calc(100vw-2rem)] bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-full px-2 py-2 sm:px-3 sm:py-3 shadow-sm", "data-billing-switch": true, children: billingOptions.map(option => {
314
316
  const isActive = option.key === billingType;
315
317
  const buttonClasses = isActive
316
318
  ? utils.cn('text-white rounded-full shadow-sm', lib.themeButtonGradientClass, lib.themeButtonGradientHoverClass)
317
319
  : 'text-gray-800 dark:text-gray-200 hover:text-gray-900 dark:hover:text-gray-100 rounded-full';
318
320
  const showBadge = option.key === billingType && !!discountBadgeText;
319
- return (jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center mx-1", children: [showBadge && (jsxRuntime.jsx("span", { className: "absolute z-10 left-1/2 -translate-x-1/2 -top-3 sm:-top-4 translate-y-[-50%] px-3 py-0.5 text-[0.625rem] sm:text-xs rounded-md bg-yellow-100 text-yellow-800 font-semibold shadow-sm whitespace-nowrap", children: discountBadgeText })), jsxRuntime.jsx("button", { className: utils.cn('text-sm md:text-base font-medium transition relative text-center z-10 px-2 sm:px-4 py-2 min-w-[100px] sm:min-w-[120px]', buttonClasses), type: "button", "data-billing-button": option.key, onClick: () => setUserSelectedBillingType(option.key), children: option.name })] }, option.key));
320
- }) }) }), jsxRuntime.jsx("div", { className: "w-full", children: jsxRuntime.jsx("div", { className: "flex flex-wrap justify-center gap-5 md:gap-6 xl:gap-8 w-full max-w-6xl mx-auto", children: currentPlans.map((plan) => {
321
+ return (jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center mx-1", children: [showBadge && (jsxRuntime.jsx("span", { className: "absolute z-10 left-1/2 -translate-x-1/2 -top-3 sm:-top-4 translate-y-[-50%] px-3 py-0.5 text-[0.625rem] sm:text-xs rounded-md bg-yellow-100 text-yellow-800 font-semibold shadow-sm whitespace-nowrap", children: discountBadgeText })), jsxRuntime.jsx("button", { className: utils.cn('text-sm md:text-base font-medium transition relative text-center z-10 px-2 sm:px-4 py-2 min-w-[88px] min-[360px]:min-w-[100px] sm:min-w-[120px]', buttonClasses), type: "button", "data-billing-button": option.key, onClick: () => setUserSelectedBillingType(option.key), children: option.name })] }, option.key));
322
+ }) }) })) : null, jsxRuntime.jsx("div", { className: "w-full", children: jsxRuntime.jsx("div", { className: "flex flex-wrap justify-center gap-5 md:gap-6 xl:gap-8 w-full max-w-6xl mx-auto", children: currentPlans.map((plan) => {
321
323
  var _a, _b;
322
324
  const planKey = plan.key;
323
325
  if (!PLAN_KEYS.includes(planKey)) {
@@ -15,7 +15,7 @@ import 'animejs';
15
15
  import '../anime/anime-404-page.mjs';
16
16
 
17
17
  const PLAN_KEYS = ['F1', 'P2', 'U3'];
18
- function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, enabledBillingTypes, enableSubscriptionUpgrade = true, initialBillingType, disableAutoDetectBilling = false, initUserContext, isInitLoading = false, }) {
18
+ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, enabledBillingTypes, mobileBillingSwitchBehavior = 'static', enableSubscriptionUpgrade = true, initialBillingType, disableAutoDetectBilling = false, initUserContext, isInitLoading = false, }) {
19
19
  var _a, _b, _c, _d, _e, _f;
20
20
  const { redirectToSignIn, redirectToSignUp, user: clerkUser, openSignUp } = useClerk();
21
21
  const router = useRouter();
@@ -35,6 +35,7 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
35
35
  return acc;
36
36
  }, {});
37
37
  }, [billingOptions]);
38
+ const showBillingSwitch = billingOptions.length > 1;
38
39
  const defaultBilling = useMemo(() => {
39
40
  var _a;
40
41
  const defaultKey = data.billingSwitch.defaultKey;
@@ -307,15 +308,16 @@ function MoneyPriceInteractive({ data, config, checkoutApiEndpoint, customerPort
307
308
  return null;
308
309
  return selectedBillingOption.discountText.replace('{percent}', String(discountPercent));
309
310
  }, [selectedBillingOption, providerConfig, billingType]);
310
- // Configure the mobile floating style for BillingTypeButton.
311
- return (jsxs(Fragment, { children: [jsx("div", { className: "flex justify-center mb-6 max-md:sticky max-md:top-30 max-md:z-30 max-md:py-2 max-md:bg-transparent", children: jsx("div", { className: "inline-flex bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-full px-2 py-2 sm:px-3 sm:py-3 max-md:w-full max-md:max-w-[340px] max-md:mx-auto shadow-sm", "data-billing-switch": true, children: billingOptions.map(option => {
311
+ // Configure the mobile behavior for BillingTypeButton.
312
+ return (jsxs(Fragment, { children: [showBillingSwitch ? (jsx("div", { className: cn('mb-6 flex justify-center', mobileBillingSwitchBehavior === 'sticky' &&
313
+ 'max-md:sticky max-md:top-2 max-md:z-30 max-md:py-2 max-md:bg-transparent'), children: jsx("div", { className: "inline-flex max-w-[calc(100vw-2rem)] bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-full px-2 py-2 sm:px-3 sm:py-3 shadow-sm", "data-billing-switch": true, children: billingOptions.map(option => {
312
314
  const isActive = option.key === billingType;
313
315
  const buttonClasses = isActive
314
316
  ? cn('text-white rounded-full shadow-sm', themeButtonGradientClass, themeButtonGradientHoverClass)
315
317
  : 'text-gray-800 dark:text-gray-200 hover:text-gray-900 dark:hover:text-gray-100 rounded-full';
316
318
  const showBadge = option.key === billingType && !!discountBadgeText;
317
- return (jsxs("div", { className: "relative flex items-center justify-center mx-1", children: [showBadge && (jsx("span", { className: "absolute z-10 left-1/2 -translate-x-1/2 -top-3 sm:-top-4 translate-y-[-50%] px-3 py-0.5 text-[0.625rem] sm:text-xs rounded-md bg-yellow-100 text-yellow-800 font-semibold shadow-sm whitespace-nowrap", children: discountBadgeText })), jsx("button", { className: cn('text-sm md:text-base font-medium transition relative text-center z-10 px-2 sm:px-4 py-2 min-w-[100px] sm:min-w-[120px]', buttonClasses), type: "button", "data-billing-button": option.key, onClick: () => setUserSelectedBillingType(option.key), children: option.name })] }, option.key));
318
- }) }) }), jsx("div", { className: "w-full", children: jsx("div", { className: "flex flex-wrap justify-center gap-5 md:gap-6 xl:gap-8 w-full max-w-6xl mx-auto", children: currentPlans.map((plan) => {
319
+ return (jsxs("div", { className: "relative flex items-center justify-center mx-1", children: [showBadge && (jsx("span", { className: "absolute z-10 left-1/2 -translate-x-1/2 -top-3 sm:-top-4 translate-y-[-50%] px-3 py-0.5 text-[0.625rem] sm:text-xs rounded-md bg-yellow-100 text-yellow-800 font-semibold shadow-sm whitespace-nowrap", children: discountBadgeText })), jsx("button", { className: cn('text-sm md:text-base font-medium transition relative text-center z-10 px-2 sm:px-4 py-2 min-w-[88px] min-[360px]:min-w-[100px] sm:min-w-[120px]', buttonClasses), type: "button", "data-billing-button": option.key, onClick: () => setUserSelectedBillingType(option.key), children: option.name })] }, option.key));
320
+ }) }) })) : null, jsx("div", { className: "w-full", children: jsx("div", { className: "flex flex-wrap justify-center gap-5 md:gap-6 xl:gap-8 w-full max-w-6xl mx-auto", children: currentPlans.map((plan) => {
319
321
  var _a, _b;
320
322
  const planKey = plan.key;
321
323
  if (!PLAN_KEYS.includes(planKey)) {
@@ -81,6 +81,7 @@ export interface MoneyPriceProps {
81
81
  enableClerkModal?: boolean;
82
82
  sectionClassName?: string;
83
83
  enabledBillingTypes?: string[];
84
+ mobileBillingSwitchBehavior?: 'sticky' | 'static';
84
85
  enableSubscriptionUpgrade?: boolean;
85
86
  initUserContext?: InitUserContext;
86
87
  initialBillingType?: string;
@@ -92,6 +93,7 @@ export interface MoneyPriceInteractiveProps {
92
93
  customerPortalApiEndpoint?: string;
93
94
  enableClerkModal?: boolean;
94
95
  enabledBillingTypes?: string[];
96
+ mobileBillingSwitchBehavior?: 'sticky' | 'static';
95
97
  enableSubscriptionUpgrade?: boolean;
96
98
  initialBillingType?: string;
97
99
  disableAutoDetectBilling?: boolean;
@@ -1,2 +1,2 @@
1
1
  import type { MoneyPriceProps } from './money-price-types';
2
- export declare function MoneyPrice({ locale, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal, sectionClassName, enabledBillingTypes, enableSubscriptionUpgrade, initUserContext, initialBillingType, }: MoneyPriceProps): Promise<import("react/jsx-runtime").JSX.Element>;
2
+ export declare function MoneyPrice({ locale, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal, sectionClassName, enabledBillingTypes, mobileBillingSwitchBehavior, enableSubscriptionUpgrade, initUserContext, initialBillingType, }: MoneyPriceProps): Promise<import("react/jsx-runtime").JSX.Element>;
@@ -7,13 +7,13 @@ var moneyPriceInteractive = require('./money-price-interactive.js');
7
7
  var moneyPriceData = require('./money-price-data.js');
8
8
 
9
9
  function MoneyPrice(_a) {
10
- return tslib.__awaiter(this, arguments, void 0, function* ({ locale, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, sectionClassName, enabledBillingTypes, enableSubscriptionUpgrade = true, initUserContext, initialBillingType, }) {
10
+ return tslib.__awaiter(this, arguments, void 0, function* ({ locale, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, sectionClassName, enabledBillingTypes, mobileBillingSwitchBehavior, enableSubscriptionUpgrade = true, initUserContext, initialBillingType, }) {
11
11
  const data = yield moneyPriceData.buildMoneyPriceData({
12
12
  locale,
13
13
  currency: config.display.currency,
14
14
  enabledBillingTypes,
15
15
  });
16
- return (jsxRuntime.jsxs("section", { id: "money-pricing", className: utils.cn("px-4 py-4 md:px-16 md:py-8 mx-auto max-w-7xl scroll-mt-10", sectionClassName), children: [jsxRuntime.jsx("h2", { className: "text-3xl md:text-4xl font-bold text-center mb-3", children: data.title }), jsxRuntime.jsx("p", { className: "text-center text-gray-600 dark:text-gray-400 mb-4 text-base md:text-lg mx-auto", children: data.subtitle }), jsxRuntime.jsx(moneyPriceInteractive.MoneyPriceInteractive, { data: data, config: config, checkoutApiEndpoint: checkoutApiEndpoint, customerPortalApiEndpoint: customerPortalApiEndpoint, enableClerkModal: enableClerkModal, enabledBillingTypes: enabledBillingTypes, enableSubscriptionUpgrade: enableSubscriptionUpgrade, initUserContext: initUserContext, initialBillingType: initialBillingType })] }));
16
+ return (jsxRuntime.jsxs("section", { id: "money-pricing", className: utils.cn("px-4 py-4 md:px-16 md:py-8 mx-auto max-w-7xl scroll-mt-10", sectionClassName), children: [jsxRuntime.jsx("h2", { className: "text-3xl md:text-4xl font-bold text-center mb-3", children: data.title }), jsxRuntime.jsx("p", { className: "text-center text-gray-600 dark:text-gray-400 mb-4 text-base md:text-lg mx-auto", children: data.subtitle }), jsxRuntime.jsx(moneyPriceInteractive.MoneyPriceInteractive, { data: data, config: config, checkoutApiEndpoint: checkoutApiEndpoint, customerPortalApiEndpoint: customerPortalApiEndpoint, enableClerkModal: enableClerkModal, enabledBillingTypes: enabledBillingTypes, mobileBillingSwitchBehavior: mobileBillingSwitchBehavior, enableSubscriptionUpgrade: enableSubscriptionUpgrade, initUserContext: initUserContext, initialBillingType: initialBillingType })] }));
17
17
  });
18
18
  }
19
19
 
@@ -5,13 +5,13 @@ import { MoneyPriceInteractive } from './money-price-interactive.mjs';
5
5
  import { buildMoneyPriceData } from './money-price-data.mjs';
6
6
 
7
7
  function MoneyPrice(_a) {
8
- return __awaiter(this, arguments, void 0, function* ({ locale, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, sectionClassName, enabledBillingTypes, enableSubscriptionUpgrade = true, initUserContext, initialBillingType, }) {
8
+ return __awaiter(this, arguments, void 0, function* ({ locale, config, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, sectionClassName, enabledBillingTypes, mobileBillingSwitchBehavior, enableSubscriptionUpgrade = true, initUserContext, initialBillingType, }) {
9
9
  const data = yield buildMoneyPriceData({
10
10
  locale,
11
11
  currency: config.display.currency,
12
12
  enabledBillingTypes,
13
13
  });
14
- return (jsxs("section", { id: "money-pricing", className: cn("px-4 py-4 md:px-16 md:py-8 mx-auto max-w-7xl scroll-mt-10", sectionClassName), children: [jsx("h2", { className: "text-3xl md:text-4xl font-bold text-center mb-3", children: data.title }), jsx("p", { className: "text-center text-gray-600 dark:text-gray-400 mb-4 text-base md:text-lg mx-auto", children: data.subtitle }), jsx(MoneyPriceInteractive, { data: data, config: config, checkoutApiEndpoint: checkoutApiEndpoint, customerPortalApiEndpoint: customerPortalApiEndpoint, enableClerkModal: enableClerkModal, enabledBillingTypes: enabledBillingTypes, enableSubscriptionUpgrade: enableSubscriptionUpgrade, initUserContext: initUserContext, initialBillingType: initialBillingType })] }));
14
+ return (jsxs("section", { id: "money-pricing", className: cn("px-4 py-4 md:px-16 md:py-8 mx-auto max-w-7xl scroll-mt-10", sectionClassName), children: [jsx("h2", { className: "text-3xl md:text-4xl font-bold text-center mb-3", children: data.title }), jsx("p", { className: "text-center text-gray-600 dark:text-gray-400 mb-4 text-base md:text-lg mx-auto", children: data.subtitle }), jsx(MoneyPriceInteractive, { data: data, config: config, checkoutApiEndpoint: checkoutApiEndpoint, customerPortalApiEndpoint: customerPortalApiEndpoint, enableClerkModal: enableClerkModal, enabledBillingTypes: enabledBillingTypes, mobileBillingSwitchBehavior: mobileBillingSwitchBehavior, enableSubscriptionUpgrade: enableSubscriptionUpgrade, initUserContext: initUserContext, initialBillingType: initialBillingType })] }));
15
15
  });
16
16
  }
17
17
 
@@ -0,0 +1,33 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { InitUserContext, MoneyPriceConfig, MoneyPriceData } from './money-price-types';
3
+ export interface OpenPricingModalOptions {
4
+ billingType?: string;
5
+ }
6
+ export interface PricingModalProps {
7
+ open: boolean;
8
+ onOpenChange: (open: boolean) => void;
9
+ data: MoneyPriceData;
10
+ config: MoneyPriceConfig;
11
+ billingType?: string;
12
+ checkoutApiEndpoint?: string;
13
+ customerPortalApiEndpoint?: string;
14
+ enableClerkModal?: boolean;
15
+ enabledBillingTypes?: string[];
16
+ mobileBillingSwitchBehavior?: 'sticky' | 'static';
17
+ enableSubscriptionUpgrade?: boolean;
18
+ initUserContext?: InitUserContext;
19
+ isInitLoading?: boolean;
20
+ }
21
+ export interface PricingModalProviderProps extends Omit<PricingModalProps, 'open' | 'onOpenChange' | 'billingType'> {
22
+ children: ReactNode;
23
+ pricingContextEndpoint?: string;
24
+ }
25
+ interface PricingModalContextValue {
26
+ openPricingModal: (options?: OpenPricingModalOptions) => void;
27
+ closePricingModal: () => void;
28
+ isPricingModalOpen: boolean;
29
+ }
30
+ export declare function PricingModal({ open, onOpenChange, data, config, billingType, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal, enabledBillingTypes, mobileBillingSwitchBehavior, enableSubscriptionUpgrade, initUserContext, isInitLoading, }: PricingModalProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare function PricingModalProvider({ children, pricingContextEndpoint, initUserContext: initUserContextProp, isInitLoading: isInitLoadingProp, ...modalProps }: PricingModalProviderProps): import("react/jsx-runtime").JSX.Element;
32
+ export declare function usePricingModal(): PricingModalContextValue;
33
+ export {};
@@ -0,0 +1,109 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var tslib = require('tslib');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var icons = require('@windrun-huaiin/base-ui/icons');
7
+ var lib = require('@windrun-huaiin/base-ui/lib');
8
+ var ui = require('@windrun-huaiin/base-ui/ui');
9
+ var utils = require('@windrun-huaiin/lib/utils');
10
+ var React = require('react');
11
+ var dialogStyles = require('../alert-dialog/dialog-styles.js');
12
+ var moneyPriceInteractive = require('./money-price-interactive.js');
13
+
14
+ const emptyInitUserContext = {
15
+ fingerprintId: null,
16
+ xUser: null,
17
+ xCredit: null,
18
+ xSubscription: null,
19
+ isClerkAuthenticated: false,
20
+ };
21
+ const PricingModalContext = React.createContext(null);
22
+ function normalizeEnabledBillingTypes(data, enabledBillingTypes) {
23
+ const availableKeys = data.billingSwitch.options.map((option) => option.key);
24
+ const configuredKeys = (enabledBillingTypes === null || enabledBillingTypes === void 0 ? void 0 : enabledBillingTypes.length) ? enabledBillingTypes : availableKeys;
25
+ return Array.from(new Set(configuredKeys
26
+ .map((billingType) => billingType.trim())
27
+ .filter((billingType) => availableKeys.includes(billingType))));
28
+ }
29
+ function resolveBillingType({ data, enabledBillingTypes, requestedBillingType, }) {
30
+ var _a, _b;
31
+ const enabledKeys = normalizeEnabledBillingTypes(data, enabledBillingTypes);
32
+ if (requestedBillingType && enabledKeys.includes(requestedBillingType)) {
33
+ return requestedBillingType;
34
+ }
35
+ if (enabledKeys.includes(data.billingSwitch.defaultKey)) {
36
+ return data.billingSwitch.defaultKey;
37
+ }
38
+ return (_a = enabledKeys[0]) !== null && _a !== void 0 ? _a : (_b = data.billingSwitch.options[0]) === null || _b === void 0 ? void 0 : _b.key;
39
+ }
40
+ function PricingModal({ open, onOpenChange, data, config, billingType, checkoutApiEndpoint, customerPortalApiEndpoint, enableClerkModal = false, enabledBillingTypes, mobileBillingSwitchBehavior, enableSubscriptionUpgrade = true, initUserContext, isInitLoading = false, }) {
41
+ const resolvedBillingType = React.useMemo(() => resolveBillingType({
42
+ data,
43
+ enabledBillingTypes,
44
+ requestedBillingType: billingType,
45
+ }), [billingType, data, enabledBillingTypes]);
46
+ return (jsxRuntime.jsx(ui.AlertDialog, { open: open, onOpenChange: onOpenChange, children: open ? (jsxRuntime.jsxs(ui.AlertDialogContent, { className: utils.cn('mt-5 sm:mt-6 md:mt-10 lg:mt-15 w-[95vw] max-w-[1200px] overflow-hidden border border-slate-200 p-0 shadow-[0_32px_90px_rgba(15,23,42,0.25)] ring-1 ring-black/5 dark:border-white/12 dark:shadow-[0_40px_120px_rgba(0,0,0,0.6)] dark:ring-white/10', lib.themeMainBgColor), overlayClassName: dialogStyles.dialogThemedOverlayClass, children: [jsxRuntime.jsxs(ui.AlertDialogHeader, { className: "flex flex-row items-center justify-between border-b border-slate-200 px-6 pt-4 pb-1 dark:border-slate-800", children: [jsxRuntime.jsx(ui.AlertDialogTitle, { asChild: true, children: jsxRuntime.jsxs("div", { className: "flex flex-wrap items-baseline gap-3 text-slate-900 dark:text-white", children: [jsxRuntime.jsx("span", { className: "text-2xl font-semibold leading-tight", children: data.title }), data.subtitle ? (jsxRuntime.jsx("span", { className: "text-sm font-medium text-slate-500 dark:text-slate-300", children: data.subtitle })) : null] }) }), jsxRuntime.jsx("button", { type: "button", className: "rounded-full p-2 text-gray-400 transition hover:bg-gray-400 hover:text-gray-400 dark:text-white/80 dark:hover:bg-white/80 dark:hover:text-white/80", onClick: () => onOpenChange(false), children: jsxRuntime.jsx(icons.XIcon, { className: "h-6 w-6" }) })] }), jsxRuntime.jsx("div", { className: "max-h-[60vh] overflow-y-auto px-4 pt-2 pb-6 sm:max-h-[80vh]", children: jsxRuntime.jsx("div", { className: "mx-auto w-full", children: jsxRuntime.jsx(moneyPriceInteractive.MoneyPriceInteractive, { data: data, config: config, checkoutApiEndpoint: checkoutApiEndpoint, customerPortalApiEndpoint: customerPortalApiEndpoint, enableClerkModal: enableClerkModal, enabledBillingTypes: enabledBillingTypes, mobileBillingSwitchBehavior: mobileBillingSwitchBehavior, enableSubscriptionUpgrade: enableSubscriptionUpgrade, initialBillingType: resolvedBillingType, disableAutoDetectBilling: resolvedBillingType === 'onetime', initUserContext: initUserContext, isInitLoading: isInitLoading }, resolvedBillingType !== null && resolvedBillingType !== void 0 ? resolvedBillingType : 'default') }) })] })) : null }));
47
+ }
48
+ function PricingModalProvider(_a) {
49
+ var { children, pricingContextEndpoint, initUserContext: initUserContextProp, isInitLoading: isInitLoadingProp = false } = _a, modalProps = tslib.__rest(_a, ["children", "pricingContextEndpoint", "initUserContext", "isInitLoading"]);
50
+ const [open, setOpen] = React.useState(false);
51
+ const [requestedBillingType, setRequestedBillingType] = React.useState();
52
+ const [loadedInitUserContext, setLoadedInitUserContext] = React.useState(initUserContextProp !== null && initUserContextProp !== void 0 ? initUserContextProp : emptyInitUserContext);
53
+ const [isContextLoading, setIsContextLoading] = React.useState(false);
54
+ const loadedContextRef = React.useRef(!!initUserContextProp);
55
+ React.useEffect(() => {
56
+ if (initUserContextProp) {
57
+ loadedContextRef.current = true;
58
+ setLoadedInitUserContext(initUserContextProp);
59
+ }
60
+ }, [initUserContextProp]);
61
+ const loadPricingContext = React.useCallback(() => tslib.__awaiter(this, void 0, void 0, function* () {
62
+ if (!pricingContextEndpoint || loadedContextRef.current) {
63
+ return;
64
+ }
65
+ setIsContextLoading(true);
66
+ try {
67
+ const response = yield fetch(pricingContextEndpoint, {
68
+ credentials: 'same-origin',
69
+ });
70
+ if (!response.ok) {
71
+ return;
72
+ }
73
+ const nextContext = (yield response.json());
74
+ loadedContextRef.current = true;
75
+ setLoadedInitUserContext(nextContext);
76
+ }
77
+ catch (error) {
78
+ console.warn('[PricingModalProvider] Failed to load pricing context', error);
79
+ }
80
+ finally {
81
+ setIsContextLoading(false);
82
+ }
83
+ }), [pricingContextEndpoint]);
84
+ const openPricingModal = React.useCallback((options) => {
85
+ setRequestedBillingType(options === null || options === void 0 ? void 0 : options.billingType);
86
+ setOpen(true);
87
+ void loadPricingContext();
88
+ }, [loadPricingContext]);
89
+ const closePricingModal = React.useCallback(() => {
90
+ setOpen(false);
91
+ }, []);
92
+ const contextValue = React.useMemo(() => ({
93
+ openPricingModal,
94
+ closePricingModal,
95
+ isPricingModalOpen: open,
96
+ }), [closePricingModal, open, openPricingModal]);
97
+ return (jsxRuntime.jsxs(PricingModalContext.Provider, { value: contextValue, children: [children, jsxRuntime.jsx(PricingModal, Object.assign({}, modalProps, { open: open, onOpenChange: setOpen, billingType: requestedBillingType, initUserContext: initUserContextProp !== null && initUserContextProp !== void 0 ? initUserContextProp : loadedInitUserContext, isInitLoading: isInitLoadingProp || isContextLoading }))] }));
98
+ }
99
+ function usePricingModal() {
100
+ const context = React.useContext(PricingModalContext);
101
+ if (!context) {
102
+ throw new Error('usePricingModal must be used within PricingModalProvider.');
103
+ }
104
+ return context;
105
+ }
106
+
107
+ exports.PricingModal = PricingModal;
108
+ exports.PricingModalProvider = PricingModalProvider;
109
+ exports.usePricingModal = usePricingModal;