@windrun-huaiin/third-ui 31.3.6 → 31.3.7
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/main/credit/credit-overview-client.js +6 -3
- package/dist/main/credit/credit-overview-client.mjs +7 -4
- package/dist/main/credit/credit-overview-nav-client.d.ts +6 -1
- package/dist/main/credit/credit-overview-nav-client.js +20 -4
- package/dist/main/credit/credit-overview-nav-client.mjs +20 -4
- package/package.json +3 -3
- package/src/main/credit/credit-overview-client.tsx +36 -25
- package/src/main/credit/credit-overview-nav-client.tsx +43 -3
|
@@ -17,7 +17,7 @@ const formatNumber = (locale, value) => new Intl.NumberFormat(locale, {
|
|
|
17
17
|
maximumFractionDigits: 0,
|
|
18
18
|
}).format(value);
|
|
19
19
|
function CreditOverviewClient({ data, locale, translations, className, expiringSoonThresholdDays = 7, customActionHandlers, }) {
|
|
20
|
-
var _a;
|
|
20
|
+
var _a, _b;
|
|
21
21
|
const { redirectToSignIn } = nextjs.useClerk();
|
|
22
22
|
const navPopover = creditNavButton.useCreditNavPopover();
|
|
23
23
|
const isMobile = (_a = navPopover === null || navPopover === void 0 ? void 0 : navPopover.isMobile) !== null && _a !== void 0 ? _a : false;
|
|
@@ -59,6 +59,9 @@ function CreditOverviewClient({ data, locale, translations, className, expiringS
|
|
|
59
59
|
const subscription = data.subscription;
|
|
60
60
|
const pricingContext = data.pricingContext;
|
|
61
61
|
const ctaBehaviors = data.ctaBehaviors;
|
|
62
|
+
const billingOptions = (_b = pricingContext === null || pricingContext === void 0 ? void 0 : pricingContext.moneyPriceData.billingSwitch.options) !== null && _b !== void 0 ? _b : [];
|
|
63
|
+
const subscriptionBillingEnabled = billingOptions.some((option) => option.key === 'monthly' || option.key === 'yearly');
|
|
64
|
+
const onetimeBillingEnabled = billingOptions.some((option) => option.key === 'onetime');
|
|
62
65
|
const getModalMoneyPriceData = React.useCallback((mode) => {
|
|
63
66
|
if (!pricingContext) {
|
|
64
67
|
return null;
|
|
@@ -232,10 +235,10 @@ function CreditOverviewClient({ data, locale, translations, className, expiringS
|
|
|
232
235
|
userToggledRef.current = true;
|
|
233
236
|
setBucketExpanded(true);
|
|
234
237
|
}, []);
|
|
235
|
-
return (jsxRuntime.jsxs("section", { className: utils.cn("flex flex-col gap-2 p-2 shadow-inner rounded-xl bg-white dark:bg-slate-900", className), children: [jsxRuntime.jsxs("header", { className: "relative rounded-2xl bg-linear-to-bl from-indigo-200/60 via-indigo-400/90 to-purple-200/50 p-4 shadow-inner dark:from-indigo-300/20 dark:via-slate-400 dark:to-slate-500/50 sm:p-6", children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 sm:gap-3", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-start rounded-full ", children: [jsxRuntime.jsx(icons.GemIcon, { "aria-hidden": true, className: "mr-2 h-6 w-6 sm:h-8 sm:w-8" }), jsxRuntime.jsx("span", { className: "text-base sm:text-lg", children: translations.totalLabel })] }), jsxRuntime.jsx("div", { className: "flex justify-center text-3xl font-semibold leading-tight sm:text-4xl", children: formatNumber(locale, data.totalBalance) }), jsxRuntime.jsxs("div", { className: "flex-1 flex-col gap-1", children: [jsxRuntime.jsx("p", { className: "text-xs text-gray-700 dark:text-slate-100 sm:text-sm", children: translations.subscriptionPeriodLabel }), jsxRuntime.jsx("h4", { className: "text-xl font-semibold sm:text-2xl", children: subscription ? subscription.planName : translations.subscriptionInactive })] }), jsxRuntime.jsx("div", { className: "pt-2 sm:pt-0", children: jsxRuntime.jsx(gradientButton.GradientButton, { title: subscription ? translations.subscriptionManage : translations.subscribePay, align: "center", icon: subscription ? jsxRuntime.jsx(icons.Settings2Icon, {}) : jsxRuntime.jsx(icons.BellIcon, {}), openInNewTab: false, className: "w-full", onClick: subscription ? handleManageAction : handleSubscribeAction }) })] }), jsxRuntime.jsx("div", { className: "absolute right-3 top-3 sm:right-6 sm:top-6", children: jsxRuntime.jsx(HoverInfo, { label: translations.totalLabel, description: translations.summaryDescription }) })] }), jsxRuntime.jsxs("section", { className: "relative flex flex-col gap-3 rounded-2xl border p-4 shadow-inner sm:gap-2 sm:p-5", children: [jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [jsxRuntime.jsx("h3", { className: "text-base text-gray-500 dark:text-slate-100 sm:text-lg", children: translations.bucketsTitle }), hasBuckets ? (jsxRuntime.jsx("button", { type: "button", "aria-expanded": bucketExpanded, "aria-label": bucketExpanded ? translations.hiddenDetail : translations.expandDetail, onClick: toggleBucketExpanded, className: "flex h-7 w-7 items-center justify-center rounded-full border border-transparent bg-white text-purple-600 shadow-[0_6px_20px_rgba(99,102,241,0.25)] transition-colors hover:text-purple-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-purple-500 dark:bg-[#1b1541] dark:text-purple-100 dark:hover:text-purple-50 dark:shadow-[0_6px_22px_rgba(112,86,255,0.35)]", children: bucketExpanded ? (jsxRuntime.jsx(icons.ChevronUpIcon, { className: "h-4 w-4" })) : (jsxRuntime.jsx(icons.ChevronDownIcon, { className: "h-4 w-4" })) })) : null] }), hasBuckets ? (bucketExpanded ? (jsxRuntime.jsx("ul", { className: "flex flex-col gap-2", children: buckets.map((bucket) => {
|
|
238
|
+
return (jsxRuntime.jsxs("section", { className: utils.cn("flex flex-col gap-2 p-2 shadow-inner rounded-xl bg-white dark:bg-slate-900", className), children: [jsxRuntime.jsxs("header", { className: "relative rounded-2xl bg-linear-to-bl from-indigo-200/60 via-indigo-400/90 to-purple-200/50 p-4 shadow-inner dark:from-indigo-300/20 dark:via-slate-400 dark:to-slate-500/50 sm:p-6", children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 sm:gap-3", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-start rounded-full ", children: [jsxRuntime.jsx(icons.GemIcon, { "aria-hidden": true, className: "mr-2 h-6 w-6 sm:h-8 sm:w-8" }), jsxRuntime.jsx("span", { className: "text-base sm:text-lg", children: translations.totalLabel })] }), jsxRuntime.jsx("div", { className: "flex justify-center text-3xl font-semibold leading-tight sm:text-4xl", children: formatNumber(locale, data.totalBalance) }), subscriptionBillingEnabled ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "flex-1 flex-col gap-1", children: [jsxRuntime.jsx("p", { className: "text-xs text-gray-700 dark:text-slate-100 sm:text-sm", children: translations.subscriptionPeriodLabel }), jsxRuntime.jsx("h4", { className: "text-xl font-semibold sm:text-2xl", children: subscription ? subscription.planName : translations.subscriptionInactive })] }), jsxRuntime.jsx("div", { className: "pt-2 sm:pt-0", children: jsxRuntime.jsx(gradientButton.GradientButton, { title: subscription ? translations.subscriptionManage : translations.subscribePay, align: "center", icon: subscription ? jsxRuntime.jsx(icons.Settings2Icon, {}) : jsxRuntime.jsx(icons.BellIcon, {}), openInNewTab: false, className: "w-full", onClick: subscription ? handleManageAction : handleSubscribeAction }) })] })) : null] }), jsxRuntime.jsx("div", { className: "absolute right-3 top-3 sm:right-6 sm:top-6", children: jsxRuntime.jsx(HoverInfo, { label: translations.totalLabel, description: translations.summaryDescription }) })] }), jsxRuntime.jsxs("section", { className: "relative flex flex-col gap-3 rounded-2xl border p-4 shadow-inner sm:gap-2 sm:p-5", children: [jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [jsxRuntime.jsx("h3", { className: "text-base text-gray-500 dark:text-slate-100 sm:text-lg", children: translations.bucketsTitle }), hasBuckets ? (jsxRuntime.jsx("button", { type: "button", "aria-expanded": bucketExpanded, "aria-label": bucketExpanded ? translations.hiddenDetail : translations.expandDetail, onClick: toggleBucketExpanded, className: "flex h-7 w-7 items-center justify-center rounded-full border border-transparent bg-white text-purple-600 shadow-[0_6px_20px_rgba(99,102,241,0.25)] transition-colors hover:text-purple-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-purple-500 dark:bg-[#1b1541] dark:text-purple-100 dark:hover:text-purple-50 dark:shadow-[0_6px_22px_rgba(112,86,255,0.35)]", children: bucketExpanded ? (jsxRuntime.jsx(icons.ChevronUpIcon, { className: "h-4 w-4" })) : (jsxRuntime.jsx(icons.ChevronDownIcon, { className: "h-4 w-4" })) })) : null] }), hasBuckets ? (bucketExpanded ? (jsxRuntime.jsx("ul", { className: "flex flex-col gap-2", children: buckets.map((bucket) => {
|
|
236
239
|
const balanceDisplay = formatNumber(locale, bucket.balance);
|
|
237
240
|
return (jsxRuntime.jsxs("li", { "data-credit-kind": bucket.kind, className: "rounded-2xl border border-slate-200/70 bg-white/85 px-3 py-3 text-sm shadow-sm transition-transform hover:-translate-y-0.5 hover:shadow-md dark:border-slate-800/60 dark:bg-slate-900/60 sm:px-4", children: [jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_auto] items-center gap-3 text-xs sm:text-sm", children: [jsxRuntime.jsx("span", { className: "flex min-w-0 items-center gap-2", children: jsxRuntime.jsx("span", { className: "max-w-full truncate rounded-full bg-purple-50 px-2 py-1 text-xs text-purple-600 shadow-sm dark:bg-purple-500/20 dark:text-purple-100 sm:text-sm", children: bucket.computedLabel }) }), jsxRuntime.jsx("span", { className: "flex min-w-0 justify-end", children: jsxRuntime.jsx("span", { className: "text-right text-base font-semibold leading-tight text-gray-500 dark:text-slate-100 sm:text-lg", title: balanceDisplay, children: balanceDisplay }) })] }), jsxRuntime.jsx("div", { className: "mt-3 flex justify-end gap-2", children: jsxRuntime.jsxs("span", { className: "text-[11px] text-gray-500 dark:text-slate-100 sm:text-xs", children: [translations.expiredAtLabel, ": ", bucket.expiresAt] }) })] }, bucket.kind));
|
|
238
|
-
}) })) : (jsxRuntime.jsx("button", { type: "button", onClick: expandBuckets, className: "w-full rounded-2xl border border-slate-200/70 bg-white/85 p-6 sm:px-4 text-sm shadow-sm transition-transform hover:-translate-y-0.5 hover:shadow-md dark:border-slate-800/60 dark:bg-slate-900/60 hover:text-purple-500", children: translations.expandDetail }))) : (jsxRuntime.jsx("div", { className: "w-full rounded-2xl border border-slate-200/70 bg-white/85 p-6 sm:px-4 text-sm shadow-sm transition-transform dark:border-slate-800/60 dark:bg-slate-900/60 text-center", children: translations.bucketsEmpty })), jsxRuntime.jsx(gradientButton.GradientButton, { title: translations.onetimeBuy, icon: jsxRuntime.jsx(icons.ShoppingCartIcon, {}), align: "center", className: "w-full text-sm sm:text-base", onClick: handleOnetimeAction })] })] }));
|
|
241
|
+
}) })) : (jsxRuntime.jsx("button", { type: "button", onClick: expandBuckets, className: "w-full rounded-2xl border border-slate-200/70 bg-white/85 p-6 sm:px-4 text-sm shadow-sm transition-transform hover:-translate-y-0.5 hover:shadow-md dark:border-slate-800/60 dark:bg-slate-900/60 hover:text-purple-500", children: translations.expandDetail }))) : (jsxRuntime.jsx("div", { className: "w-full rounded-2xl border border-slate-200/70 bg-white/85 p-6 sm:px-4 text-sm shadow-sm transition-transform dark:border-slate-800/60 dark:bg-slate-900/60 text-center", children: translations.bucketsEmpty })), onetimeBillingEnabled ? (jsxRuntime.jsx(gradientButton.GradientButton, { title: translations.onetimeBuy, icon: jsxRuntime.jsx(icons.ShoppingCartIcon, {}), align: "center", className: "w-full text-sm sm:text-base", onClick: handleOnetimeAction })) : null] })] }));
|
|
239
242
|
}
|
|
240
243
|
function deriveStatus(expiresAt, thresholdDays = 7) {
|
|
241
244
|
if (!expiresAt) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { __awaiter } from 'tslib';
|
|
3
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import { useClerk } from '@clerk/nextjs';
|
|
5
5
|
import { GradientButton } from '../buttons/gradient-button.mjs';
|
|
6
6
|
import { useState, useRef, useCallback, useMemo, useLayoutEffect } from 'react';
|
|
@@ -15,7 +15,7 @@ const formatNumber = (locale, value) => new Intl.NumberFormat(locale, {
|
|
|
15
15
|
maximumFractionDigits: 0,
|
|
16
16
|
}).format(value);
|
|
17
17
|
function CreditOverviewClient({ data, locale, translations, className, expiringSoonThresholdDays = 7, customActionHandlers, }) {
|
|
18
|
-
var _a;
|
|
18
|
+
var _a, _b;
|
|
19
19
|
const { redirectToSignIn } = useClerk();
|
|
20
20
|
const navPopover = useCreditNavPopover();
|
|
21
21
|
const isMobile = (_a = navPopover === null || navPopover === void 0 ? void 0 : navPopover.isMobile) !== null && _a !== void 0 ? _a : false;
|
|
@@ -57,6 +57,9 @@ function CreditOverviewClient({ data, locale, translations, className, expiringS
|
|
|
57
57
|
const subscription = data.subscription;
|
|
58
58
|
const pricingContext = data.pricingContext;
|
|
59
59
|
const ctaBehaviors = data.ctaBehaviors;
|
|
60
|
+
const billingOptions = (_b = pricingContext === null || pricingContext === void 0 ? void 0 : pricingContext.moneyPriceData.billingSwitch.options) !== null && _b !== void 0 ? _b : [];
|
|
61
|
+
const subscriptionBillingEnabled = billingOptions.some((option) => option.key === 'monthly' || option.key === 'yearly');
|
|
62
|
+
const onetimeBillingEnabled = billingOptions.some((option) => option.key === 'onetime');
|
|
60
63
|
const getModalMoneyPriceData = useCallback((mode) => {
|
|
61
64
|
if (!pricingContext) {
|
|
62
65
|
return null;
|
|
@@ -230,10 +233,10 @@ function CreditOverviewClient({ data, locale, translations, className, expiringS
|
|
|
230
233
|
userToggledRef.current = true;
|
|
231
234
|
setBucketExpanded(true);
|
|
232
235
|
}, []);
|
|
233
|
-
return (jsxs("section", { className: cn("flex flex-col gap-2 p-2 shadow-inner rounded-xl bg-white dark:bg-slate-900", className), children: [jsxs("header", { className: "relative rounded-2xl bg-linear-to-bl from-indigo-200/60 via-indigo-400/90 to-purple-200/50 p-4 shadow-inner dark:from-indigo-300/20 dark:via-slate-400 dark:to-slate-500/50 sm:p-6", children: [jsxs("div", { className: "flex flex-col gap-2 sm:gap-3", children: [jsxs("div", { className: "flex items-center justify-start rounded-full ", children: [jsx(GemIcon, { "aria-hidden": true, className: "mr-2 h-6 w-6 sm:h-8 sm:w-8" }), jsx("span", { className: "text-base sm:text-lg", children: translations.totalLabel })] }), jsx("div", { className: "flex justify-center text-3xl font-semibold leading-tight sm:text-4xl", children: formatNumber(locale, data.totalBalance) }), jsxs("div", { className: "flex-1 flex-col gap-1", children: [jsx("p", { className: "text-xs text-gray-700 dark:text-slate-100 sm:text-sm", children: translations.subscriptionPeriodLabel }), jsx("h4", { className: "text-xl font-semibold sm:text-2xl", children: subscription ? subscription.planName : translations.subscriptionInactive })] }), jsx("div", { className: "pt-2 sm:pt-0", children: jsx(GradientButton, { title: subscription ? translations.subscriptionManage : translations.subscribePay, align: "center", icon: subscription ? jsx(Settings2Icon, {}) : jsx(BellIcon, {}), openInNewTab: false, className: "w-full", onClick: subscription ? handleManageAction : handleSubscribeAction }) })] }), jsx("div", { className: "absolute right-3 top-3 sm:right-6 sm:top-6", children: jsx(HoverInfo, { label: translations.totalLabel, description: translations.summaryDescription }) })] }), jsxs("section", { className: "relative flex flex-col gap-3 rounded-2xl border p-4 shadow-inner sm:gap-2 sm:p-5", children: [jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [jsx("h3", { className: "text-base text-gray-500 dark:text-slate-100 sm:text-lg", children: translations.bucketsTitle }), hasBuckets ? (jsx("button", { type: "button", "aria-expanded": bucketExpanded, "aria-label": bucketExpanded ? translations.hiddenDetail : translations.expandDetail, onClick: toggleBucketExpanded, className: "flex h-7 w-7 items-center justify-center rounded-full border border-transparent bg-white text-purple-600 shadow-[0_6px_20px_rgba(99,102,241,0.25)] transition-colors hover:text-purple-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-purple-500 dark:bg-[#1b1541] dark:text-purple-100 dark:hover:text-purple-50 dark:shadow-[0_6px_22px_rgba(112,86,255,0.35)]", children: bucketExpanded ? (jsx(ChevronUpIcon, { className: "h-4 w-4" })) : (jsx(ChevronDownIcon, { className: "h-4 w-4" })) })) : null] }), hasBuckets ? (bucketExpanded ? (jsx("ul", { className: "flex flex-col gap-2", children: buckets.map((bucket) => {
|
|
236
|
+
return (jsxs("section", { className: cn("flex flex-col gap-2 p-2 shadow-inner rounded-xl bg-white dark:bg-slate-900", className), children: [jsxs("header", { className: "relative rounded-2xl bg-linear-to-bl from-indigo-200/60 via-indigo-400/90 to-purple-200/50 p-4 shadow-inner dark:from-indigo-300/20 dark:via-slate-400 dark:to-slate-500/50 sm:p-6", children: [jsxs("div", { className: "flex flex-col gap-2 sm:gap-3", children: [jsxs("div", { className: "flex items-center justify-start rounded-full ", children: [jsx(GemIcon, { "aria-hidden": true, className: "mr-2 h-6 w-6 sm:h-8 sm:w-8" }), jsx("span", { className: "text-base sm:text-lg", children: translations.totalLabel })] }), jsx("div", { className: "flex justify-center text-3xl font-semibold leading-tight sm:text-4xl", children: formatNumber(locale, data.totalBalance) }), subscriptionBillingEnabled ? (jsxs(Fragment, { children: [jsxs("div", { className: "flex-1 flex-col gap-1", children: [jsx("p", { className: "text-xs text-gray-700 dark:text-slate-100 sm:text-sm", children: translations.subscriptionPeriodLabel }), jsx("h4", { className: "text-xl font-semibold sm:text-2xl", children: subscription ? subscription.planName : translations.subscriptionInactive })] }), jsx("div", { className: "pt-2 sm:pt-0", children: jsx(GradientButton, { title: subscription ? translations.subscriptionManage : translations.subscribePay, align: "center", icon: subscription ? jsx(Settings2Icon, {}) : jsx(BellIcon, {}), openInNewTab: false, className: "w-full", onClick: subscription ? handleManageAction : handleSubscribeAction }) })] })) : null] }), jsx("div", { className: "absolute right-3 top-3 sm:right-6 sm:top-6", children: jsx(HoverInfo, { label: translations.totalLabel, description: translations.summaryDescription }) })] }), jsxs("section", { className: "relative flex flex-col gap-3 rounded-2xl border p-4 shadow-inner sm:gap-2 sm:p-5", children: [jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [jsx("h3", { className: "text-base text-gray-500 dark:text-slate-100 sm:text-lg", children: translations.bucketsTitle }), hasBuckets ? (jsx("button", { type: "button", "aria-expanded": bucketExpanded, "aria-label": bucketExpanded ? translations.hiddenDetail : translations.expandDetail, onClick: toggleBucketExpanded, className: "flex h-7 w-7 items-center justify-center rounded-full border border-transparent bg-white text-purple-600 shadow-[0_6px_20px_rgba(99,102,241,0.25)] transition-colors hover:text-purple-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-purple-500 dark:bg-[#1b1541] dark:text-purple-100 dark:hover:text-purple-50 dark:shadow-[0_6px_22px_rgba(112,86,255,0.35)]", children: bucketExpanded ? (jsx(ChevronUpIcon, { className: "h-4 w-4" })) : (jsx(ChevronDownIcon, { className: "h-4 w-4" })) })) : null] }), hasBuckets ? (bucketExpanded ? (jsx("ul", { className: "flex flex-col gap-2", children: buckets.map((bucket) => {
|
|
234
237
|
const balanceDisplay = formatNumber(locale, bucket.balance);
|
|
235
238
|
return (jsxs("li", { "data-credit-kind": bucket.kind, className: "rounded-2xl border border-slate-200/70 bg-white/85 px-3 py-3 text-sm shadow-sm transition-transform hover:-translate-y-0.5 hover:shadow-md dark:border-slate-800/60 dark:bg-slate-900/60 sm:px-4", children: [jsxs("div", { className: "grid grid-cols-[1fr_auto] items-center gap-3 text-xs sm:text-sm", children: [jsx("span", { className: "flex min-w-0 items-center gap-2", children: jsx("span", { className: "max-w-full truncate rounded-full bg-purple-50 px-2 py-1 text-xs text-purple-600 shadow-sm dark:bg-purple-500/20 dark:text-purple-100 sm:text-sm", children: bucket.computedLabel }) }), jsx("span", { className: "flex min-w-0 justify-end", children: jsx("span", { className: "text-right text-base font-semibold leading-tight text-gray-500 dark:text-slate-100 sm:text-lg", title: balanceDisplay, children: balanceDisplay }) })] }), jsx("div", { className: "mt-3 flex justify-end gap-2", children: jsxs("span", { className: "text-[11px] text-gray-500 dark:text-slate-100 sm:text-xs", children: [translations.expiredAtLabel, ": ", bucket.expiresAt] }) })] }, bucket.kind));
|
|
236
|
-
}) })) : (jsx("button", { type: "button", onClick: expandBuckets, className: "w-full rounded-2xl border border-slate-200/70 bg-white/85 p-6 sm:px-4 text-sm shadow-sm transition-transform hover:-translate-y-0.5 hover:shadow-md dark:border-slate-800/60 dark:bg-slate-900/60 hover:text-purple-500", children: translations.expandDetail }))) : (jsx("div", { className: "w-full rounded-2xl border border-slate-200/70 bg-white/85 p-6 sm:px-4 text-sm shadow-sm transition-transform dark:border-slate-800/60 dark:bg-slate-900/60 text-center", children: translations.bucketsEmpty })), jsx(GradientButton, { title: translations.onetimeBuy, icon: jsx(ShoppingCartIcon, {}), align: "center", className: "w-full text-sm sm:text-base", onClick: handleOnetimeAction })] })] }));
|
|
239
|
+
}) })) : (jsx("button", { type: "button", onClick: expandBuckets, className: "w-full rounded-2xl border border-slate-200/70 bg-white/85 p-6 sm:px-4 text-sm shadow-sm transition-transform hover:-translate-y-0.5 hover:shadow-md dark:border-slate-800/60 dark:bg-slate-900/60 hover:text-purple-500", children: translations.expandDetail }))) : (jsx("div", { className: "w-full rounded-2xl border border-slate-200/70 bg-white/85 p-6 sm:px-4 text-sm shadow-sm transition-transform dark:border-slate-800/60 dark:bg-slate-900/60 text-center", children: translations.bucketsEmpty })), onetimeBillingEnabled ? (jsx(GradientButton, { title: translations.onetimeBuy, icon: jsx(ShoppingCartIcon, {}), align: "center", className: "w-full text-sm sm:text-base", onClick: handleOnetimeAction })) : null] })] }));
|
|
237
240
|
}
|
|
238
241
|
function deriveStatus(expiresAt, thresholdDays = 7) {
|
|
239
242
|
if (!expiresAt) {
|
|
@@ -9,6 +9,11 @@ export interface CreditOverviewPayload {
|
|
|
9
9
|
export interface CreditOverviewNavClientProps {
|
|
10
10
|
locale: string;
|
|
11
11
|
endpoint: string;
|
|
12
|
+
/**
|
|
13
|
+
* Billing types enabled by the business app.
|
|
14
|
+
* Defaults are handled by the API/payload builder when omitted.
|
|
15
|
+
*/
|
|
16
|
+
enabledBillingTypes?: string[];
|
|
12
17
|
/**
|
|
13
18
|
* Browser event names that should trigger credit overview reload.
|
|
14
19
|
* Business apps can dispatch these events after credit balance changes.
|
|
@@ -24,4 +29,4 @@ export interface CreditOverviewNavClientProps {
|
|
|
24
29
|
refreshDebounceMs?: number;
|
|
25
30
|
}
|
|
26
31
|
export declare function dispatchCreditOverviewRefresh(eventName?: string): void;
|
|
27
|
-
export declare function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebounceMs, }: CreditOverviewNavClientProps): import("react/jsx-runtime").JSX.Element | null;
|
|
32
|
+
export declare function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, refreshEvents, refreshDebounceMs, }: CreditOverviewNavClientProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -9,9 +9,23 @@ var creditNavButton = require('./credit-nav-button.js');
|
|
|
9
9
|
var creditOverviewClient = require('./credit-overview-client.js');
|
|
10
10
|
|
|
11
11
|
const DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = 'windrun-huaiin:credit-overview:refresh';
|
|
12
|
-
function
|
|
12
|
+
function normalizeEnabledBillingTypes(enabledBillingTypes) {
|
|
13
|
+
if (!(enabledBillingTypes === null || enabledBillingTypes === void 0 ? void 0 : enabledBillingTypes.length)) {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
return Array.from(new Set(enabledBillingTypes
|
|
17
|
+
.map((billingType) => billingType.trim())
|
|
18
|
+
.filter((billingType) => billingType.length > 0)));
|
|
19
|
+
}
|
|
20
|
+
function buildEnabledBillingTypesKey(enabledBillingTypes) {
|
|
21
|
+
return normalizeEnabledBillingTypes(enabledBillingTypes).join('\n');
|
|
22
|
+
}
|
|
23
|
+
function buildCreditOverviewUrl(endpoint, locale, enabledBillingTypes) {
|
|
13
24
|
const url = new URL(endpoint, window.location.origin);
|
|
14
25
|
url.searchParams.set('locale', locale);
|
|
26
|
+
for (const billingType of enabledBillingTypes) {
|
|
27
|
+
url.searchParams.append('enabledBillingTypes', billingType);
|
|
28
|
+
}
|
|
15
29
|
return url.toString();
|
|
16
30
|
}
|
|
17
31
|
function normalizeRefreshEvents(refreshEvents) {
|
|
@@ -29,13 +43,15 @@ function dispatchCreditOverviewRefresh(eventName = DEFAULT_CREDIT_OVERVIEW_REFRE
|
|
|
29
43
|
}
|
|
30
44
|
window.dispatchEvent(new CustomEvent(eventName));
|
|
31
45
|
}
|
|
32
|
-
function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebounceMs = 300, }) {
|
|
46
|
+
function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, refreshEvents, refreshDebounceMs = 300, }) {
|
|
33
47
|
const { isLoaded, isSignedIn, userId } = nextjs.useAuth();
|
|
34
48
|
const [payload, setPayload] = React.useState(null);
|
|
35
49
|
const abortControllerRef = React.useRef(null);
|
|
36
50
|
const isMountedRef = React.useRef(false);
|
|
37
51
|
const refreshEventsKey = buildRefreshEventsKey(refreshEvents);
|
|
38
52
|
const normalizedRefreshEvents = React.useMemo(() => refreshEventsKey.split('\n').filter(Boolean), [refreshEventsKey]);
|
|
53
|
+
const enabledBillingTypesKey = buildEnabledBillingTypesKey(enabledBillingTypes);
|
|
54
|
+
const normalizedEnabledBillingTypes = React.useMemo(() => enabledBillingTypesKey.split('\n').filter(Boolean), [enabledBillingTypesKey]);
|
|
39
55
|
React.useEffect(() => {
|
|
40
56
|
isMountedRef.current = true;
|
|
41
57
|
return () => {
|
|
@@ -50,7 +66,7 @@ function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebou
|
|
|
50
66
|
const controller = new AbortController();
|
|
51
67
|
abortControllerRef.current = controller;
|
|
52
68
|
try {
|
|
53
|
-
const response = yield fetch(buildCreditOverviewUrl(endpoint, locale), {
|
|
69
|
+
const response = yield fetch(buildCreditOverviewUrl(endpoint, locale, normalizedEnabledBillingTypes), {
|
|
54
70
|
cache: 'no-store',
|
|
55
71
|
credentials: 'same-origin',
|
|
56
72
|
signal: controller.signal,
|
|
@@ -77,7 +93,7 @@ function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebou
|
|
|
77
93
|
abortControllerRef.current = null;
|
|
78
94
|
}
|
|
79
95
|
}
|
|
80
|
-
}), [endpoint, locale]);
|
|
96
|
+
}), [endpoint, locale, normalizedEnabledBillingTypes]);
|
|
81
97
|
React.useEffect(() => {
|
|
82
98
|
var _a;
|
|
83
99
|
if (!isLoaded) {
|
|
@@ -7,9 +7,23 @@ import { CreditNavButton } from './credit-nav-button.mjs';
|
|
|
7
7
|
import { CreditOverviewClient } from './credit-overview-client.mjs';
|
|
8
8
|
|
|
9
9
|
const DEFAULT_CREDIT_OVERVIEW_REFRESH_EVENT = 'windrun-huaiin:credit-overview:refresh';
|
|
10
|
-
function
|
|
10
|
+
function normalizeEnabledBillingTypes(enabledBillingTypes) {
|
|
11
|
+
if (!(enabledBillingTypes === null || enabledBillingTypes === void 0 ? void 0 : enabledBillingTypes.length)) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
return Array.from(new Set(enabledBillingTypes
|
|
15
|
+
.map((billingType) => billingType.trim())
|
|
16
|
+
.filter((billingType) => billingType.length > 0)));
|
|
17
|
+
}
|
|
18
|
+
function buildEnabledBillingTypesKey(enabledBillingTypes) {
|
|
19
|
+
return normalizeEnabledBillingTypes(enabledBillingTypes).join('\n');
|
|
20
|
+
}
|
|
21
|
+
function buildCreditOverviewUrl(endpoint, locale, enabledBillingTypes) {
|
|
11
22
|
const url = new URL(endpoint, window.location.origin);
|
|
12
23
|
url.searchParams.set('locale', locale);
|
|
24
|
+
for (const billingType of enabledBillingTypes) {
|
|
25
|
+
url.searchParams.append('enabledBillingTypes', billingType);
|
|
26
|
+
}
|
|
13
27
|
return url.toString();
|
|
14
28
|
}
|
|
15
29
|
function normalizeRefreshEvents(refreshEvents) {
|
|
@@ -27,13 +41,15 @@ function dispatchCreditOverviewRefresh(eventName = DEFAULT_CREDIT_OVERVIEW_REFRE
|
|
|
27
41
|
}
|
|
28
42
|
window.dispatchEvent(new CustomEvent(eventName));
|
|
29
43
|
}
|
|
30
|
-
function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebounceMs = 300, }) {
|
|
44
|
+
function CreditOverviewNavClient({ locale, endpoint, enabledBillingTypes, refreshEvents, refreshDebounceMs = 300, }) {
|
|
31
45
|
const { isLoaded, isSignedIn, userId } = useAuth();
|
|
32
46
|
const [payload, setPayload] = useState(null);
|
|
33
47
|
const abortControllerRef = useRef(null);
|
|
34
48
|
const isMountedRef = useRef(false);
|
|
35
49
|
const refreshEventsKey = buildRefreshEventsKey(refreshEvents);
|
|
36
50
|
const normalizedRefreshEvents = useMemo(() => refreshEventsKey.split('\n').filter(Boolean), [refreshEventsKey]);
|
|
51
|
+
const enabledBillingTypesKey = buildEnabledBillingTypesKey(enabledBillingTypes);
|
|
52
|
+
const normalizedEnabledBillingTypes = useMemo(() => enabledBillingTypesKey.split('\n').filter(Boolean), [enabledBillingTypesKey]);
|
|
37
53
|
useEffect(() => {
|
|
38
54
|
isMountedRef.current = true;
|
|
39
55
|
return () => {
|
|
@@ -48,7 +64,7 @@ function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebou
|
|
|
48
64
|
const controller = new AbortController();
|
|
49
65
|
abortControllerRef.current = controller;
|
|
50
66
|
try {
|
|
51
|
-
const response = yield fetch(buildCreditOverviewUrl(endpoint, locale), {
|
|
67
|
+
const response = yield fetch(buildCreditOverviewUrl(endpoint, locale, normalizedEnabledBillingTypes), {
|
|
52
68
|
cache: 'no-store',
|
|
53
69
|
credentials: 'same-origin',
|
|
54
70
|
signal: controller.signal,
|
|
@@ -75,7 +91,7 @@ function CreditOverviewNavClient({ locale, endpoint, refreshEvents, refreshDebou
|
|
|
75
91
|
abortControllerRef.current = null;
|
|
76
92
|
}
|
|
77
93
|
}
|
|
78
|
-
}), [endpoint, locale]);
|
|
94
|
+
}), [endpoint, locale, normalizedEnabledBillingTypes]);
|
|
79
95
|
useEffect(() => {
|
|
80
96
|
var _a;
|
|
81
97
|
if (!isLoaded) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windrun-huaiin/third-ui",
|
|
3
|
-
"version": "31.3.
|
|
3
|
+
"version": "31.3.7",
|
|
4
4
|
"description": "Third-party integrated UI components for windrun-huaiin projects",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./clerk": {
|
|
@@ -243,9 +243,9 @@
|
|
|
243
243
|
"tslib": "^2.8.1",
|
|
244
244
|
"unified": "^11.0.5",
|
|
245
245
|
"zod": "^4.3.6",
|
|
246
|
-
"@windrun-huaiin/base-ui": "^31.0.1",
|
|
247
246
|
"@windrun-huaiin/contracts": "^31.0.0",
|
|
248
|
-
"@windrun-huaiin/lib": "^31.0.3"
|
|
247
|
+
"@windrun-huaiin/lib": "^31.0.3",
|
|
248
|
+
"@windrun-huaiin/base-ui": "^31.0.1"
|
|
249
249
|
},
|
|
250
250
|
"peerDependencies": {
|
|
251
251
|
"clsx": "^2.1.1",
|
|
@@ -128,6 +128,11 @@ export function CreditOverviewClient({
|
|
|
128
128
|
const subscription = data.subscription;
|
|
129
129
|
const pricingContext = data.pricingContext;
|
|
130
130
|
const ctaBehaviors = data.ctaBehaviors;
|
|
131
|
+
const billingOptions = pricingContext?.moneyPriceData.billingSwitch.options ?? [];
|
|
132
|
+
const subscriptionBillingEnabled = billingOptions.some(
|
|
133
|
+
(option) => option.key === 'monthly' || option.key === 'yearly',
|
|
134
|
+
);
|
|
135
|
+
const onetimeBillingEnabled = billingOptions.some((option) => option.key === 'onetime');
|
|
131
136
|
const getModalMoneyPriceData = useCallback(
|
|
132
137
|
(mode: PricingModalMode) => {
|
|
133
138
|
if (!pricingContext) {
|
|
@@ -383,24 +388,28 @@ export function CreditOverviewClient({
|
|
|
383
388
|
<div className="flex justify-center text-3xl font-semibold leading-tight sm:text-4xl">
|
|
384
389
|
{formatNumber(locale, data.totalBalance)}
|
|
385
390
|
</div>
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
391
|
+
{subscriptionBillingEnabled ? (
|
|
392
|
+
<>
|
|
393
|
+
<div className="flex-1 flex-col gap-1">
|
|
394
|
+
<p className="text-xs text-gray-700 dark:text-slate-100 sm:text-sm">
|
|
395
|
+
{translations.subscriptionPeriodLabel}
|
|
396
|
+
</p>
|
|
397
|
+
<h4 className="text-xl font-semibold sm:text-2xl">
|
|
398
|
+
{subscription ? subscription.planName : translations.subscriptionInactive}
|
|
399
|
+
</h4>
|
|
400
|
+
</div>
|
|
401
|
+
<div className="pt-2 sm:pt-0">
|
|
402
|
+
<GradientButton
|
|
403
|
+
title={subscription ? translations.subscriptionManage : translations.subscribePay}
|
|
404
|
+
align="center"
|
|
405
|
+
icon={subscription ? <Settings2Icon /> : <BellIcon />}
|
|
406
|
+
openInNewTab={false}
|
|
407
|
+
className="w-full"
|
|
408
|
+
onClick={subscription ? handleManageAction : handleSubscribeAction}
|
|
409
|
+
/>
|
|
410
|
+
</div>
|
|
411
|
+
</>
|
|
412
|
+
) : null}
|
|
404
413
|
</div>
|
|
405
414
|
<div className="absolute right-3 top-3 sm:right-6 sm:top-6">
|
|
406
415
|
<HoverInfo
|
|
@@ -482,13 +491,15 @@ export function CreditOverviewClient({
|
|
|
482
491
|
{translations.bucketsEmpty}
|
|
483
492
|
</div>
|
|
484
493
|
)}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
494
|
+
{onetimeBillingEnabled ? (
|
|
495
|
+
<GradientButton
|
|
496
|
+
title={translations.onetimeBuy}
|
|
497
|
+
icon={<ShoppingCartIcon />}
|
|
498
|
+
align="center"
|
|
499
|
+
className="w-full text-sm sm:text-base"
|
|
500
|
+
onClick={handleOnetimeAction}
|
|
501
|
+
/>
|
|
502
|
+
) : null}
|
|
492
503
|
</section>
|
|
493
504
|
</section>
|
|
494
505
|
);
|
|
@@ -17,6 +17,11 @@ export interface CreditOverviewPayload {
|
|
|
17
17
|
export interface CreditOverviewNavClientProps {
|
|
18
18
|
locale: string;
|
|
19
19
|
endpoint: string;
|
|
20
|
+
/**
|
|
21
|
+
* Billing types enabled by the business app.
|
|
22
|
+
* Defaults are handled by the API/payload builder when omitted.
|
|
23
|
+
*/
|
|
24
|
+
enabledBillingTypes?: string[];
|
|
20
25
|
/**
|
|
21
26
|
* Browser event names that should trigger credit overview reload.
|
|
22
27
|
* Business apps can dispatch these events after credit balance changes.
|
|
@@ -32,9 +37,34 @@ export interface CreditOverviewNavClientProps {
|
|
|
32
37
|
refreshDebounceMs?: number;
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
function
|
|
40
|
+
function normalizeEnabledBillingTypes(enabledBillingTypes: string[] | undefined) {
|
|
41
|
+
if (!enabledBillingTypes?.length) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return Array.from(
|
|
46
|
+
new Set(
|
|
47
|
+
enabledBillingTypes
|
|
48
|
+
.map((billingType) => billingType.trim())
|
|
49
|
+
.filter((billingType) => billingType.length > 0),
|
|
50
|
+
),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function buildEnabledBillingTypesKey(enabledBillingTypes: string[] | undefined) {
|
|
55
|
+
return normalizeEnabledBillingTypes(enabledBillingTypes).join('\n');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function buildCreditOverviewUrl(
|
|
59
|
+
endpoint: string,
|
|
60
|
+
locale: string,
|
|
61
|
+
enabledBillingTypes: string[],
|
|
62
|
+
) {
|
|
36
63
|
const url = new URL(endpoint, window.location.origin);
|
|
37
64
|
url.searchParams.set('locale', locale);
|
|
65
|
+
for (const billingType of enabledBillingTypes) {
|
|
66
|
+
url.searchParams.append('enabledBillingTypes', billingType);
|
|
67
|
+
}
|
|
38
68
|
return url.toString();
|
|
39
69
|
}
|
|
40
70
|
|
|
@@ -66,6 +96,7 @@ export function dispatchCreditOverviewRefresh(
|
|
|
66
96
|
export function CreditOverviewNavClient({
|
|
67
97
|
locale,
|
|
68
98
|
endpoint,
|
|
99
|
+
enabledBillingTypes,
|
|
69
100
|
refreshEvents,
|
|
70
101
|
refreshDebounceMs = 300,
|
|
71
102
|
}: CreditOverviewNavClientProps) {
|
|
@@ -78,6 +109,11 @@ export function CreditOverviewNavClient({
|
|
|
78
109
|
() => refreshEventsKey.split('\n').filter(Boolean),
|
|
79
110
|
[refreshEventsKey],
|
|
80
111
|
);
|
|
112
|
+
const enabledBillingTypesKey = buildEnabledBillingTypesKey(enabledBillingTypes);
|
|
113
|
+
const normalizedEnabledBillingTypes = useMemo(
|
|
114
|
+
() => enabledBillingTypesKey.split('\n').filter(Boolean),
|
|
115
|
+
[enabledBillingTypesKey],
|
|
116
|
+
);
|
|
81
117
|
|
|
82
118
|
useEffect(() => {
|
|
83
119
|
isMountedRef.current = true;
|
|
@@ -95,7 +131,11 @@ export function CreditOverviewNavClient({
|
|
|
95
131
|
abortControllerRef.current = controller;
|
|
96
132
|
|
|
97
133
|
try {
|
|
98
|
-
const response = await fetch(buildCreditOverviewUrl(
|
|
134
|
+
const response = await fetch(buildCreditOverviewUrl(
|
|
135
|
+
endpoint,
|
|
136
|
+
locale,
|
|
137
|
+
normalizedEnabledBillingTypes,
|
|
138
|
+
), {
|
|
99
139
|
cache: 'no-store',
|
|
100
140
|
credentials: 'same-origin',
|
|
101
141
|
signal: controller.signal,
|
|
@@ -122,7 +162,7 @@ export function CreditOverviewNavClient({
|
|
|
122
162
|
abortControllerRef.current = null;
|
|
123
163
|
}
|
|
124
164
|
}
|
|
125
|
-
}, [endpoint, locale]);
|
|
165
|
+
}, [endpoint, locale, normalizedEnabledBillingTypes]);
|
|
126
166
|
|
|
127
167
|
useEffect(() => {
|
|
128
168
|
if (!isLoaded) {
|