@windrun-huaiin/third-ui 7.3.2 → 7.3.4
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/clerk/fingerprint/fingerprint-provider.js +26 -6
- package/dist/clerk/fingerprint/fingerprint-provider.mjs +27 -7
- package/dist/clerk/fingerprint/use-fingerprint.js +1 -1
- package/dist/clerk/fingerprint/use-fingerprint.mjs +1 -1
- package/dist/main/faq.js +11 -0
- package/dist/main/faq.mjs +11 -0
- package/dist/main/gallery.js +11 -0
- package/dist/main/gallery.mjs +11 -0
- package/dist/main/index.d.ts +2 -0
- package/dist/main/index.js +4 -0
- package/dist/main/index.mjs +2 -0
- package/dist/main/money-price/money-price-button.d.ts +2 -0
- package/dist/main/money-price/money-price-button.js +96 -0
- package/dist/main/money-price/money-price-button.mjs +94 -0
- package/dist/main/money-price/money-price-config-util.d.ts +7 -0
- package/dist/main/money-price/money-price-config-util.js +19 -0
- package/dist/main/money-price/money-price-config-util.mjs +16 -0
- package/dist/main/money-price/money-price-config.d.ts +8 -0
- package/dist/main/money-price/money-price-config.js +223 -0
- package/dist/main/money-price/money-price-config.mjs +219 -0
- package/dist/main/money-price/money-price-interactive.d.ts +2 -0
- package/dist/main/money-price/money-price-interactive.js +315 -0
- package/dist/main/money-price/money-price-interactive.mjs +313 -0
- package/dist/main/money-price/money-price-types.d.ts +116 -0
- package/dist/main/money-price/money-price-types.js +14 -0
- package/dist/main/money-price/money-price-types.mjs +14 -0
- package/dist/main/money-price/money-price.d.ts +2 -0
- package/dist/main/money-price/money-price.js +93 -0
- package/dist/main/money-price/money-price.mjs +91 -0
- package/dist/main/price-plan.js +12 -0
- package/dist/main/price-plan.mjs +12 -0
- package/dist/main/server.d.ts +4 -0
- package/dist/main/server.js +10 -0
- package/dist/main/server.mjs +3 -0
- package/dist/node_modules/.pnpm/cose-base@1.0.3/node_modules/cose-base/cose-base.js +1 -1
- package/dist/node_modules/.pnpm/cose-base@1.0.3/node_modules/cose-base/cose-base.mjs +1 -1
- package/dist/node_modules/.pnpm/cose-base@2.2.0/node_modules/cose-base/cose-base.js +1 -1
- package/dist/node_modules/.pnpm/cose-base@2.2.0/node_modules/cose-base/cose-base.mjs +1 -1
- package/dist/node_modules/.pnpm/layout-base@1.0.2/node_modules/layout-base/layout-base.js +1 -1
- package/dist/node_modules/.pnpm/layout-base@2.0.1/node_modules/layout-base/layout-base.js +1 -1
- package/package.json +1 -1
- package/src/clerk/fingerprint/fingerprint-provider.tsx +53 -20
- package/src/clerk/fingerprint/use-fingerprint.ts +1 -1
- package/src/main/index.ts +5 -1
- package/src/main/money-price/money-price-button.tsx +105 -0
- package/src/main/money-price/money-price-config-util.ts +23 -0
- package/src/main/money-price/money-price-interactive.tsx +381 -0
- package/src/main/money-price/money-price-types.ts +138 -0
- package/src/main/money-price/money-price.tsx +307 -0
- package/src/main/server.ts +24 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Money Price Component Types
|
|
3
|
+
* 价格组件类型定义
|
|
4
|
+
*/
|
|
5
|
+
export declare enum UserState {
|
|
6
|
+
Anonymous = "anonymous",
|
|
7
|
+
FreeUser = "free",
|
|
8
|
+
ProUser = "pro",
|
|
9
|
+
UltraUser = "ultra"
|
|
10
|
+
}
|
|
11
|
+
export interface UserContext {
|
|
12
|
+
isAuthenticated: boolean;
|
|
13
|
+
subscriptionStatus: UserState;
|
|
14
|
+
subscriptionType?: 'monthly' | 'yearly';
|
|
15
|
+
subscriptionEndDate?: string;
|
|
16
|
+
}
|
|
17
|
+
export type PaymentProvider = 'stripe' | 'apple' | 'paypal' | 'wechat' | 'alipay';
|
|
18
|
+
export interface EnhancePricePlan {
|
|
19
|
+
priceId: string;
|
|
20
|
+
amount: number;
|
|
21
|
+
originalAmount?: number;
|
|
22
|
+
discountPercent?: number;
|
|
23
|
+
currency: string;
|
|
24
|
+
credits?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface ProductConfig {
|
|
27
|
+
key: string;
|
|
28
|
+
name: string;
|
|
29
|
+
plans: {
|
|
30
|
+
monthly: EnhancePricePlan;
|
|
31
|
+
yearly: EnhancePricePlan;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface PaymentProviderConfig {
|
|
35
|
+
provider: PaymentProvider;
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
products: {
|
|
38
|
+
free: ProductConfig;
|
|
39
|
+
pro: ProductConfig;
|
|
40
|
+
ultra: ProductConfig;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface MoneyPriceConfig {
|
|
44
|
+
paymentProviders: {
|
|
45
|
+
[provider: string]: PaymentProviderConfig;
|
|
46
|
+
};
|
|
47
|
+
activeProvider: string;
|
|
48
|
+
display: {
|
|
49
|
+
currency: string;
|
|
50
|
+
locale: string;
|
|
51
|
+
minFeaturesCount: number;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export interface MoneyPriceProps {
|
|
55
|
+
locale: string;
|
|
56
|
+
config: MoneyPriceConfig;
|
|
57
|
+
className?: string;
|
|
58
|
+
upgradeApiEndpoint?: string;
|
|
59
|
+
signInPath?: string;
|
|
60
|
+
sectionClassName?: string;
|
|
61
|
+
}
|
|
62
|
+
export interface MoneyPriceInteractiveProps {
|
|
63
|
+
data: MoneyPriceData;
|
|
64
|
+
config: MoneyPriceConfig;
|
|
65
|
+
upgradeApiEndpoint?: string;
|
|
66
|
+
signInPath?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface MoneyPriceButtonProps {
|
|
69
|
+
planKey: 'free' | 'pro' | 'ultra';
|
|
70
|
+
userContext: UserContext;
|
|
71
|
+
billingType: 'monthly' | 'yearly';
|
|
72
|
+
onLogin: () => void;
|
|
73
|
+
onUpgrade: (plan: string, billingType: string) => void | Promise<void>;
|
|
74
|
+
texts: {
|
|
75
|
+
getStarted: string;
|
|
76
|
+
getPro: string;
|
|
77
|
+
getUltra: string;
|
|
78
|
+
currentPlan: string;
|
|
79
|
+
upgrade: string;
|
|
80
|
+
};
|
|
81
|
+
isProcessing?: boolean;
|
|
82
|
+
}
|
|
83
|
+
export interface MoneyPriceData {
|
|
84
|
+
title: string;
|
|
85
|
+
subtitle: string;
|
|
86
|
+
billingSwitch: {
|
|
87
|
+
options: Array<{
|
|
88
|
+
key: string;
|
|
89
|
+
name: string;
|
|
90
|
+
unit: string;
|
|
91
|
+
discountText: string;
|
|
92
|
+
subTitle?: string;
|
|
93
|
+
}>;
|
|
94
|
+
defaultKey: string;
|
|
95
|
+
};
|
|
96
|
+
plans: Array<{
|
|
97
|
+
key: string;
|
|
98
|
+
title: string;
|
|
99
|
+
showBillingSubTitle?: boolean;
|
|
100
|
+
titleTags?: string[];
|
|
101
|
+
features?: Array<{
|
|
102
|
+
description: string;
|
|
103
|
+
icon?: string;
|
|
104
|
+
tag?: string;
|
|
105
|
+
tooltip?: string;
|
|
106
|
+
}>;
|
|
107
|
+
}>;
|
|
108
|
+
buttonTexts: {
|
|
109
|
+
getStarted: string;
|
|
110
|
+
getPro: string;
|
|
111
|
+
getUltra: string;
|
|
112
|
+
currentPlan: string;
|
|
113
|
+
upgrade: string;
|
|
114
|
+
};
|
|
115
|
+
currency: string;
|
|
116
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Money Price Component Types
|
|
5
|
+
* 价格组件类型定义
|
|
6
|
+
*/
|
|
7
|
+
// 用户状态枚举
|
|
8
|
+
exports.UserState = void 0;
|
|
9
|
+
(function (UserState) {
|
|
10
|
+
UserState["Anonymous"] = "anonymous";
|
|
11
|
+
UserState["FreeUser"] = "free";
|
|
12
|
+
UserState["ProUser"] = "pro";
|
|
13
|
+
UserState["UltraUser"] = "ultra";
|
|
14
|
+
})(exports.UserState || (exports.UserState = {}));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Money Price Component Types
|
|
3
|
+
* 价格组件类型定义
|
|
4
|
+
*/
|
|
5
|
+
// 用户状态枚举
|
|
6
|
+
var UserState;
|
|
7
|
+
(function (UserState) {
|
|
8
|
+
UserState["Anonymous"] = "anonymous";
|
|
9
|
+
UserState["FreeUser"] = "free";
|
|
10
|
+
UserState["ProUser"] = "pro";
|
|
11
|
+
UserState["UltraUser"] = "ultra";
|
|
12
|
+
})(UserState || (UserState = {}));
|
|
13
|
+
|
|
14
|
+
export { UserState };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib_es6 = require('../../node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.2/node_modules/tslib/tslib.es6.js');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
require('@windrun-huaiin/base-ui/components/server');
|
|
6
|
+
require('next-themes');
|
|
7
|
+
require('react');
|
|
8
|
+
require('fumadocs-core/framework');
|
|
9
|
+
var utils = require('@windrun-huaiin/lib/utils');
|
|
10
|
+
require('next/link');
|
|
11
|
+
var gradientButton = require('../../fuma/mdx/gradient-button.js');
|
|
12
|
+
require('next/navigation');
|
|
13
|
+
require('fumadocs-ui/utils/use-copy-button');
|
|
14
|
+
require('fumadocs-core/link');
|
|
15
|
+
require('@windrun-huaiin/base-ui/ui');
|
|
16
|
+
require('fumadocs-ui/components/ui/collapsible');
|
|
17
|
+
require('../../fuma/mdx/banner.js');
|
|
18
|
+
var server = require('next-intl/server');
|
|
19
|
+
var moneyPriceConfigUtil = require('./money-price-config-util.js');
|
|
20
|
+
var moneyPriceInteractive = require('./money-price-interactive.js');
|
|
21
|
+
|
|
22
|
+
function MoneyPrice(_a) {
|
|
23
|
+
return tslib_es6.__awaiter(this, arguments, void 0, function* ({ locale, config, upgradeApiEndpoint, signInPath, sectionClassName }) {
|
|
24
|
+
var _b, _c;
|
|
25
|
+
const t = yield server.getTranslations({ locale, namespace: 'moneyPrice' });
|
|
26
|
+
const data = {
|
|
27
|
+
title: t('title'),
|
|
28
|
+
subtitle: t('subtitle'),
|
|
29
|
+
billingSwitch: t.raw('billingSwitch'),
|
|
30
|
+
plans: t.raw('plans'),
|
|
31
|
+
buttonTexts: t.raw('buttonTexts'),
|
|
32
|
+
currency: config.display.currency
|
|
33
|
+
};
|
|
34
|
+
// 获取激活的支付供应商配置
|
|
35
|
+
const providerConfig = moneyPriceConfigUtil.getActiveProviderConfig(config);
|
|
36
|
+
const minPlanFeaturesCount = config.display.minFeaturesCount;
|
|
37
|
+
// 使用默认计费类型进行静态渲染
|
|
38
|
+
const defaultBilling = data.billingSwitch.defaultKey;
|
|
39
|
+
const defaultBillingDisplay = data.billingSwitch.options.find((opt) => opt.key === defaultBilling) || data.billingSwitch.options[0];
|
|
40
|
+
// 计算特性数量
|
|
41
|
+
const maxFeaturesCount = Math.max(...data.plans.map((plan) => { var _a; return ((_a = plan.features) === null || _a === void 0 ? void 0 : _a.length) || 0; }), minPlanFeaturesCount || 0);
|
|
42
|
+
// 处理卡片高度对齐
|
|
43
|
+
const getFeatureRows = (plan) => {
|
|
44
|
+
const features = plan.features || [];
|
|
45
|
+
const filled = [...features];
|
|
46
|
+
while (filled.length < maxFeaturesCount)
|
|
47
|
+
filled.push(null);
|
|
48
|
+
return filled;
|
|
49
|
+
};
|
|
50
|
+
// 静态价格渲染逻辑
|
|
51
|
+
function renderPrice(plan, billingKey = data.billingSwitch.defaultKey) {
|
|
52
|
+
const productConfig = providerConfig.products[plan.key];
|
|
53
|
+
const pricing = productConfig.plans[billingKey];
|
|
54
|
+
const currentBillingDisplay = data.billingSwitch.options.find((opt) => opt.key === billingKey) || defaultBillingDisplay;
|
|
55
|
+
const billingSubTitle = (currentBillingDisplay === null || currentBillingDisplay === void 0 ? void 0 : currentBillingDisplay.subTitle) || '';
|
|
56
|
+
// 免费计划
|
|
57
|
+
if (pricing.amount === 0) {
|
|
58
|
+
return (jsxRuntime.jsxs("div", { className: "flex flex-col items-start w-full", "data-price-container": plan.key, children: [jsxRuntime.jsx("div", { className: "flex items-end gap-2", children: jsxRuntime.jsx("span", { className: "text-4xl font-extrabold text-gray-900 dark:text-gray-100", "data-price-value": plan.key, children: "Free" }) }), jsxRuntime.jsx("div", { className: "flex items-center gap-2 min-h-[24px] mt-1", children: jsxRuntime.jsx("span", { className: utils.cn('text-xs text-gray-700 dark:text-gray-300 font-medium', plan.showBillingSubTitle === false && 'opacity-0 select-none'), "data-price-subtitle": plan.key, children: plan.showBillingSubTitle === false ? '' : billingSubTitle }) })] }));
|
|
59
|
+
}
|
|
60
|
+
// 付费计划
|
|
61
|
+
const hasDiscount = pricing.discountPercent && pricing.discountPercent > 0;
|
|
62
|
+
const unit = currentBillingDisplay.unit || '';
|
|
63
|
+
let discountText = '';
|
|
64
|
+
if (hasDiscount && currentBillingDisplay.discountText) {
|
|
65
|
+
discountText = currentBillingDisplay.discountText.replace('{percent}', String(pricing.discountPercent));
|
|
66
|
+
}
|
|
67
|
+
return (jsxRuntime.jsxs("div", { className: "flex flex-col items-start w-full", "data-price-container": plan.key, children: [jsxRuntime.jsxs("div", { className: "flex items-end gap-2", children: [jsxRuntime.jsxs("span", { className: "text-4xl font-extrabold text-gray-900 dark:text-gray-100", "data-price-value": plan.key, children: [data.currency, pricing.amount] }), jsxRuntime.jsx("span", { className: "text-lg text-gray-700 dark:text-gray-300 font-medium mb-1", "data-price-unit": plan.key, children: unit })] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-h-[24px] mt-1", children: [hasDiscount && pricing.originalAmount && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("span", { className: "text-base text-gray-400 line-through", "data-price-original": plan.key, children: [data.currency, pricing.originalAmount] }), discountText && (jsxRuntime.jsx("span", { className: "px-2 py-0.5 text-xs rounded bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 font-semibold align-middle", "data-price-discount": plan.key, children: discountText }))] })), jsxRuntime.jsx("span", { className: utils.cn('text-xs text-gray-700 dark:text-gray-300 font-medium', plan.showBillingSubTitle === false && 'opacity-0 select-none'), "data-price-subtitle": plan.key, children: plan.showBillingSubTitle === false ? '' : billingSubTitle })] })] }));
|
|
68
|
+
}
|
|
69
|
+
return (jsxRuntime.jsxs("section", { id: "money-pricing", className: utils.cn("px-4 py-10 md:px-16 md:py-16 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-8 text-base md:text-lg mx-auto", children: data.subtitle }), jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [jsxRuntime.jsx("div", { className: "flex items-center relative mb-3", children: jsxRuntime.jsxs("div", { className: "flex bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-full p-1", "data-billing-switch": true, children: [jsxRuntime.jsx("button", { className: utils.cn('min-w-[120px] px-6 py-2 font-medium transition text-lg relative', data.billingSwitch.defaultKey === 'monthly'
|
|
70
|
+
? 'text-white bg-gradient-to-r from-purple-400 to-pink-500 hover:from-purple-500 hover:to-pink-600 dark:from-purple-500 dark:to-pink-600 dark:hover:from-purple-600 rounded-full shadow-sm'
|
|
71
|
+
: 'text-gray-800 dark:text-gray-200 hover:text-gray-900 dark:hover:text-gray-100 rounded-full'), "data-billing-button": "monthly", type: "button", children: ((_b = data.billingSwitch.options.find((opt) => opt.key === 'monthly')) === null || _b === void 0 ? void 0 : _b.name) || 'Monthly' }), jsxRuntime.jsx("button", { className: utils.cn('min-w-[120px] px-6 py-2 font-medium transition text-lg relative', data.billingSwitch.defaultKey === 'yearly'
|
|
72
|
+
? 'text-white bg-gradient-to-r from-purple-400 to-pink-500 hover:from-purple-500 hover:to-pink-600 dark:from-purple-500 dark:to-pink-600 dark:hover:from-purple-600 rounded-full shadow-sm'
|
|
73
|
+
: 'text-gray-800 dark:text-gray-200 hover:text-gray-900 dark:hover:text-gray-100 rounded-full'), "data-billing-button": "yearly", type: "button", children: ((_c = data.billingSwitch.options.find((opt) => opt.key === 'yearly')) === null || _c === void 0 ? void 0 : _c.name) || 'Yearly' })] }) }), jsxRuntime.jsx("div", { className: "h-8 flex items-center justify-center mb-3", "data-discount-info": true, children: (() => {
|
|
74
|
+
const opt = data.billingSwitch.options.find((opt) => opt.key === data.billingSwitch.defaultKey);
|
|
75
|
+
// 检查默认计费类型是否有折扣
|
|
76
|
+
let hasDiscount = false;
|
|
77
|
+
let discountPercent = 0;
|
|
78
|
+
['pro', 'ultra'].forEach(planKey => {
|
|
79
|
+
const product = providerConfig.products[planKey];
|
|
80
|
+
const pricing = product.plans[data.billingSwitch.defaultKey];
|
|
81
|
+
if (pricing.discountPercent) {
|
|
82
|
+
hasDiscount = true;
|
|
83
|
+
discountPercent = pricing.discountPercent;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
if (!(opt && hasDiscount && opt.discountText))
|
|
87
|
+
return null;
|
|
88
|
+
return (jsxRuntime.jsx("span", { className: "px-2 py-1 text-xs rounded bg-yellow-100 text-yellow-800 font-semibold align-middle text-center inline-flex items-center justify-center whitespace-nowrap", children: opt.discountText.replace('{percent}', String(discountPercent)) }));
|
|
89
|
+
})() })] }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-8", children: data.plans.map((plan, _idx) => (jsxRuntime.jsxs("div", { "data-price-plan": plan.key, className: utils.cn('flex flex-col bg-white dark:bg-gray-800/60 rounded-2xl border border-gray-300 dark:border-[#7c3aed40] transition p-8 h-full shadow-sm dark:shadow-none', 'hover:border-2 hover:border-purple-500', 'focus-within:border-2 focus-within:border-purple-500'), style: { minHeight: maxFeaturesCount * 100 }, children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-2", children: [jsxRuntime.jsx("span", { className: "text-xl font-bold text-gray-900 dark:text-gray-100", children: plan.title }), plan.titleTags && plan.titleTags.map((tag, i) => (jsxRuntime.jsx("span", { className: "px-2 py-0.5 text-xs rounded bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200 font-semibold align-middle", children: tag }, i)))] }), renderPrice(plan), jsxRuntime.jsx("ul", { className: "flex-1 mb-6 mt-4", children: getFeatureRows(plan).map((feature, i) => (jsxRuntime.jsxs("li", { className: "flex items-center gap-2 mb-2 min-h-[28px]", "data-feature-item": `${plan.key}-${i}`, children: [feature ? (jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-200 mr-1", children: feature.icon ? jsxRuntime.jsx("span", { children: feature.icon }) : jsxRuntime.jsx("span", { className: "font-bold", children: "\u2713" }) })) : (jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full mr-1", children: "\u00A0" })), feature && feature.tag && (jsxRuntime.jsx("span", { className: "px-1 py-0.5 text-[6px] rounded bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 font-semibold align-middle", children: feature.tag })), feature ? (jsxRuntime.jsxs("span", { className: "relative group cursor-pointer text-sm text-gray-800 dark:text-gray-200", children: [feature.description, feature.tooltip && (jsxRuntime.jsx("span", { className: "ml-1 align-middle inline-flex", "data-tooltip-trigger": `${plan.key}-${i}`, "data-tooltip-content": feature.tooltip, children: jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }) }))] })) : (jsxRuntime.jsx("span", { children: "\u00A0" }))] }, i))) }), jsxRuntime.jsx("div", { className: "flex-1" }), jsxRuntime.jsx("div", { "data-button-placeholder": plan.key, children: jsxRuntime.jsx(gradientButton.GradientButton, { title: data.buttonTexts.getStarted, disabled: true, align: "center", className: "w-full" }) })] }, plan.key))) }), jsxRuntime.jsx(moneyPriceInteractive.MoneyPriceInteractive, { data: data, config: config, upgradeApiEndpoint: upgradeApiEndpoint, signInPath: signInPath })] }));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
exports.MoneyPrice = MoneyPrice;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { __awaiter } from '../../node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.2/node_modules/tslib/tslib.es6.mjs';
|
|
2
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import '@windrun-huaiin/base-ui/components/server';
|
|
4
|
+
import 'next-themes';
|
|
5
|
+
import 'react';
|
|
6
|
+
import 'fumadocs-core/framework';
|
|
7
|
+
import { cn } from '@windrun-huaiin/lib/utils';
|
|
8
|
+
import 'next/link';
|
|
9
|
+
import { GradientButton } from '../../fuma/mdx/gradient-button.mjs';
|
|
10
|
+
import 'next/navigation';
|
|
11
|
+
import 'fumadocs-ui/utils/use-copy-button';
|
|
12
|
+
import 'fumadocs-core/link';
|
|
13
|
+
import '@windrun-huaiin/base-ui/ui';
|
|
14
|
+
import 'fumadocs-ui/components/ui/collapsible';
|
|
15
|
+
import '../../fuma/mdx/banner.mjs';
|
|
16
|
+
import { getTranslations } from 'next-intl/server';
|
|
17
|
+
import { getActiveProviderConfig } from './money-price-config-util.mjs';
|
|
18
|
+
import { MoneyPriceInteractive } from './money-price-interactive.mjs';
|
|
19
|
+
|
|
20
|
+
function MoneyPrice(_a) {
|
|
21
|
+
return __awaiter(this, arguments, void 0, function* ({ locale, config, upgradeApiEndpoint, signInPath, sectionClassName }) {
|
|
22
|
+
var _b, _c;
|
|
23
|
+
const t = yield getTranslations({ locale, namespace: 'moneyPrice' });
|
|
24
|
+
const data = {
|
|
25
|
+
title: t('title'),
|
|
26
|
+
subtitle: t('subtitle'),
|
|
27
|
+
billingSwitch: t.raw('billingSwitch'),
|
|
28
|
+
plans: t.raw('plans'),
|
|
29
|
+
buttonTexts: t.raw('buttonTexts'),
|
|
30
|
+
currency: config.display.currency
|
|
31
|
+
};
|
|
32
|
+
// 获取激活的支付供应商配置
|
|
33
|
+
const providerConfig = getActiveProviderConfig(config);
|
|
34
|
+
const minPlanFeaturesCount = config.display.minFeaturesCount;
|
|
35
|
+
// 使用默认计费类型进行静态渲染
|
|
36
|
+
const defaultBilling = data.billingSwitch.defaultKey;
|
|
37
|
+
const defaultBillingDisplay = data.billingSwitch.options.find((opt) => opt.key === defaultBilling) || data.billingSwitch.options[0];
|
|
38
|
+
// 计算特性数量
|
|
39
|
+
const maxFeaturesCount = Math.max(...data.plans.map((plan) => { var _a; return ((_a = plan.features) === null || _a === void 0 ? void 0 : _a.length) || 0; }), minPlanFeaturesCount || 0);
|
|
40
|
+
// 处理卡片高度对齐
|
|
41
|
+
const getFeatureRows = (plan) => {
|
|
42
|
+
const features = plan.features || [];
|
|
43
|
+
const filled = [...features];
|
|
44
|
+
while (filled.length < maxFeaturesCount)
|
|
45
|
+
filled.push(null);
|
|
46
|
+
return filled;
|
|
47
|
+
};
|
|
48
|
+
// 静态价格渲染逻辑
|
|
49
|
+
function renderPrice(plan, billingKey = data.billingSwitch.defaultKey) {
|
|
50
|
+
const productConfig = providerConfig.products[plan.key];
|
|
51
|
+
const pricing = productConfig.plans[billingKey];
|
|
52
|
+
const currentBillingDisplay = data.billingSwitch.options.find((opt) => opt.key === billingKey) || defaultBillingDisplay;
|
|
53
|
+
const billingSubTitle = (currentBillingDisplay === null || currentBillingDisplay === void 0 ? void 0 : currentBillingDisplay.subTitle) || '';
|
|
54
|
+
// 免费计划
|
|
55
|
+
if (pricing.amount === 0) {
|
|
56
|
+
return (jsxs("div", { className: "flex flex-col items-start w-full", "data-price-container": plan.key, children: [jsx("div", { className: "flex items-end gap-2", children: jsx("span", { className: "text-4xl font-extrabold text-gray-900 dark:text-gray-100", "data-price-value": plan.key, children: "Free" }) }), jsx("div", { className: "flex items-center gap-2 min-h-[24px] mt-1", children: jsx("span", { className: cn('text-xs text-gray-700 dark:text-gray-300 font-medium', plan.showBillingSubTitle === false && 'opacity-0 select-none'), "data-price-subtitle": plan.key, children: plan.showBillingSubTitle === false ? '' : billingSubTitle }) })] }));
|
|
57
|
+
}
|
|
58
|
+
// 付费计划
|
|
59
|
+
const hasDiscount = pricing.discountPercent && pricing.discountPercent > 0;
|
|
60
|
+
const unit = currentBillingDisplay.unit || '';
|
|
61
|
+
let discountText = '';
|
|
62
|
+
if (hasDiscount && currentBillingDisplay.discountText) {
|
|
63
|
+
discountText = currentBillingDisplay.discountText.replace('{percent}', String(pricing.discountPercent));
|
|
64
|
+
}
|
|
65
|
+
return (jsxs("div", { className: "flex flex-col items-start w-full", "data-price-container": plan.key, children: [jsxs("div", { className: "flex items-end gap-2", children: [jsxs("span", { className: "text-4xl font-extrabold text-gray-900 dark:text-gray-100", "data-price-value": plan.key, children: [data.currency, pricing.amount] }), jsx("span", { className: "text-lg text-gray-700 dark:text-gray-300 font-medium mb-1", "data-price-unit": plan.key, children: unit })] }), jsxs("div", { className: "flex items-center gap-2 min-h-[24px] mt-1", children: [hasDiscount && pricing.originalAmount && (jsxs(Fragment, { children: [jsxs("span", { className: "text-base text-gray-400 line-through", "data-price-original": plan.key, children: [data.currency, pricing.originalAmount] }), discountText && (jsx("span", { className: "px-2 py-0.5 text-xs rounded bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 font-semibold align-middle", "data-price-discount": plan.key, children: discountText }))] })), jsx("span", { className: cn('text-xs text-gray-700 dark:text-gray-300 font-medium', plan.showBillingSubTitle === false && 'opacity-0 select-none'), "data-price-subtitle": plan.key, children: plan.showBillingSubTitle === false ? '' : billingSubTitle })] })] }));
|
|
66
|
+
}
|
|
67
|
+
return (jsxs("section", { id: "money-pricing", className: cn("px-4 py-10 md:px-16 md:py-16 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-8 text-base md:text-lg mx-auto", children: data.subtitle }), jsxs("div", { className: "flex flex-col items-center", children: [jsx("div", { className: "flex items-center relative mb-3", children: jsxs("div", { className: "flex bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-full p-1", "data-billing-switch": true, children: [jsx("button", { className: cn('min-w-[120px] px-6 py-2 font-medium transition text-lg relative', data.billingSwitch.defaultKey === 'monthly'
|
|
68
|
+
? 'text-white bg-gradient-to-r from-purple-400 to-pink-500 hover:from-purple-500 hover:to-pink-600 dark:from-purple-500 dark:to-pink-600 dark:hover:from-purple-600 rounded-full shadow-sm'
|
|
69
|
+
: 'text-gray-800 dark:text-gray-200 hover:text-gray-900 dark:hover:text-gray-100 rounded-full'), "data-billing-button": "monthly", type: "button", children: ((_b = data.billingSwitch.options.find((opt) => opt.key === 'monthly')) === null || _b === void 0 ? void 0 : _b.name) || 'Monthly' }), jsx("button", { className: cn('min-w-[120px] px-6 py-2 font-medium transition text-lg relative', data.billingSwitch.defaultKey === 'yearly'
|
|
70
|
+
? 'text-white bg-gradient-to-r from-purple-400 to-pink-500 hover:from-purple-500 hover:to-pink-600 dark:from-purple-500 dark:to-pink-600 dark:hover:from-purple-600 rounded-full shadow-sm'
|
|
71
|
+
: 'text-gray-800 dark:text-gray-200 hover:text-gray-900 dark:hover:text-gray-100 rounded-full'), "data-billing-button": "yearly", type: "button", children: ((_c = data.billingSwitch.options.find((opt) => opt.key === 'yearly')) === null || _c === void 0 ? void 0 : _c.name) || 'Yearly' })] }) }), jsx("div", { className: "h-8 flex items-center justify-center mb-3", "data-discount-info": true, children: (() => {
|
|
72
|
+
const opt = data.billingSwitch.options.find((opt) => opt.key === data.billingSwitch.defaultKey);
|
|
73
|
+
// 检查默认计费类型是否有折扣
|
|
74
|
+
let hasDiscount = false;
|
|
75
|
+
let discountPercent = 0;
|
|
76
|
+
['pro', 'ultra'].forEach(planKey => {
|
|
77
|
+
const product = providerConfig.products[planKey];
|
|
78
|
+
const pricing = product.plans[data.billingSwitch.defaultKey];
|
|
79
|
+
if (pricing.discountPercent) {
|
|
80
|
+
hasDiscount = true;
|
|
81
|
+
discountPercent = pricing.discountPercent;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
if (!(opt && hasDiscount && opt.discountText))
|
|
85
|
+
return null;
|
|
86
|
+
return (jsx("span", { className: "px-2 py-1 text-xs rounded bg-yellow-100 text-yellow-800 font-semibold align-middle text-center inline-flex items-center justify-center whitespace-nowrap", children: opt.discountText.replace('{percent}', String(discountPercent)) }));
|
|
87
|
+
})() })] }), jsx("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-8", children: data.plans.map((plan, _idx) => (jsxs("div", { "data-price-plan": plan.key, className: cn('flex flex-col bg-white dark:bg-gray-800/60 rounded-2xl border border-gray-300 dark:border-[#7c3aed40] transition p-8 h-full shadow-sm dark:shadow-none', 'hover:border-2 hover:border-purple-500', 'focus-within:border-2 focus-within:border-purple-500'), style: { minHeight: maxFeaturesCount * 100 }, children: [jsxs("div", { className: "flex items-center gap-2 mb-2", children: [jsx("span", { className: "text-xl font-bold text-gray-900 dark:text-gray-100", children: plan.title }), plan.titleTags && plan.titleTags.map((tag, i) => (jsx("span", { className: "px-2 py-0.5 text-xs rounded bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200 font-semibold align-middle", children: tag }, i)))] }), renderPrice(plan), jsx("ul", { className: "flex-1 mb-6 mt-4", children: getFeatureRows(plan).map((feature, i) => (jsxs("li", { className: "flex items-center gap-2 mb-2 min-h-[28px]", "data-feature-item": `${plan.key}-${i}`, children: [feature ? (jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-200 mr-1", children: feature.icon ? jsx("span", { children: feature.icon }) : jsx("span", { className: "font-bold", children: "\u2713" }) })) : (jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 rounded-full mr-1", children: "\u00A0" })), feature && feature.tag && (jsx("span", { className: "px-1 py-0.5 text-[6px] rounded bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 font-semibold align-middle", children: feature.tag })), feature ? (jsxs("span", { className: "relative group cursor-pointer text-sm text-gray-800 dark:text-gray-200", children: [feature.description, feature.tooltip && (jsx("span", { className: "ml-1 align-middle inline-flex", "data-tooltip-trigger": `${plan.key}-${i}`, "data-tooltip-content": feature.tooltip, children: jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }) }))] })) : (jsx("span", { children: "\u00A0" }))] }, i))) }), jsx("div", { className: "flex-1" }), jsx("div", { "data-button-placeholder": plan.key, children: jsx(GradientButton, { title: data.buttonTexts.getStarted, disabled: true, align: "center", className: "w-full" }) })] }, plan.key))) }), jsx(MoneyPriceInteractive, { data: data, config: config, upgradeApiEndpoint: upgradeApiEndpoint, signInPath: signInPath })] }));
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { MoneyPrice };
|
package/dist/main/price-plan.js
CHANGED
|
@@ -11,6 +11,18 @@ require('next/image');
|
|
|
11
11
|
require('@windrun-huaiin/base-ui/ui');
|
|
12
12
|
require('./rich-text-expert.js');
|
|
13
13
|
var pricePlanInteractive = require('./price-plan-interactive.js');
|
|
14
|
+
require('@clerk/nextjs');
|
|
15
|
+
require('../clerk/fingerprint/fingerprint-provider.js');
|
|
16
|
+
require('next/navigation');
|
|
17
|
+
require('react-dom/client');
|
|
18
|
+
require('next-themes');
|
|
19
|
+
require('fumadocs-core/framework');
|
|
20
|
+
require('next/link');
|
|
21
|
+
require('fumadocs-ui/utils/use-copy-button');
|
|
22
|
+
require('fumadocs-core/link');
|
|
23
|
+
require('fumadocs-ui/components/ui/collapsible');
|
|
24
|
+
require('../fuma/mdx/banner.js');
|
|
25
|
+
require('./money-price/money-price-types.js');
|
|
14
26
|
|
|
15
27
|
function PricePlan(_a) {
|
|
16
28
|
return tslib_es6.__awaiter(this, arguments, void 0, function* ({ locale, currency = '$', pricePlanConfig, sectionClassName }) {
|
package/dist/main/price-plan.mjs
CHANGED
|
@@ -9,6 +9,18 @@ import 'next/image';
|
|
|
9
9
|
import '@windrun-huaiin/base-ui/ui';
|
|
10
10
|
import './rich-text-expert.mjs';
|
|
11
11
|
import { PricePlanInteractive } from './price-plan-interactive.mjs';
|
|
12
|
+
import '@clerk/nextjs';
|
|
13
|
+
import '../clerk/fingerprint/fingerprint-provider.mjs';
|
|
14
|
+
import 'next/navigation';
|
|
15
|
+
import 'react-dom/client';
|
|
16
|
+
import 'next-themes';
|
|
17
|
+
import 'fumadocs-core/framework';
|
|
18
|
+
import 'next/link';
|
|
19
|
+
import 'fumadocs-ui/utils/use-copy-button';
|
|
20
|
+
import 'fumadocs-core/link';
|
|
21
|
+
import 'fumadocs-ui/components/ui/collapsible';
|
|
22
|
+
import '../fuma/mdx/banner.mjs';
|
|
23
|
+
import './money-price/money-price-types.mjs';
|
|
12
24
|
|
|
13
25
|
function PricePlan(_a) {
|
|
14
26
|
return __awaiter(this, arguments, void 0, function* ({ locale, currency = '$', pricePlanConfig, sectionClassName }) {
|
package/dist/main/server.d.ts
CHANGED
|
@@ -7,3 +7,7 @@ export * from './seo-content';
|
|
|
7
7
|
export * from './cta';
|
|
8
8
|
export * from './footer';
|
|
9
9
|
export * from './price-plan';
|
|
10
|
+
export { MoneyPrice } from './money-price/money-price';
|
|
11
|
+
export { getActiveProviderConfig, getProductPricing } from './money-price/money-price-config-util';
|
|
12
|
+
export type { MoneyPriceConfig, MoneyPriceProps, MoneyPriceInteractiveProps, MoneyPriceButtonProps, MoneyPriceData, PaymentProvider, PaymentProviderConfig, EnhancePricePlan, ProductConfig, UserContext } from './money-price/money-price-types';
|
|
13
|
+
export { UserState } from './money-price/money-price-types';
|
package/dist/main/server.js
CHANGED
|
@@ -9,6 +9,9 @@ var seoContent = require('./seo-content.js');
|
|
|
9
9
|
var cta = require('./cta.js');
|
|
10
10
|
var footer = require('./footer.js');
|
|
11
11
|
var pricePlan = require('./price-plan.js');
|
|
12
|
+
var moneyPrice = require('./money-price/money-price.js');
|
|
13
|
+
var moneyPriceConfigUtil = require('./money-price/money-price-config-util.js');
|
|
14
|
+
var moneyPriceTypes = require('./money-price/money-price-types.js');
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
|
|
@@ -21,3 +24,10 @@ exports.SeoContent = seoContent.SeoContent;
|
|
|
21
24
|
exports.CTA = cta.CTA;
|
|
22
25
|
exports.Footer = footer.Footer;
|
|
23
26
|
exports.PricePlan = pricePlan.PricePlan;
|
|
27
|
+
exports.MoneyPrice = moneyPrice.MoneyPrice;
|
|
28
|
+
exports.getActiveProviderConfig = moneyPriceConfigUtil.getActiveProviderConfig;
|
|
29
|
+
exports.getProductPricing = moneyPriceConfigUtil.getProductPricing;
|
|
30
|
+
Object.defineProperty(exports, "UserState", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () { return moneyPriceTypes.UserState; }
|
|
33
|
+
});
|
package/dist/main/server.mjs
CHANGED
|
@@ -7,3 +7,6 @@ export { SeoContent } from './seo-content.mjs';
|
|
|
7
7
|
export { CTA } from './cta.mjs';
|
|
8
8
|
export { Footer } from './footer.mjs';
|
|
9
9
|
export { PricePlan } from './price-plan.mjs';
|
|
10
|
+
export { MoneyPrice } from './money-price/money-price.mjs';
|
|
11
|
+
export { getActiveProviderConfig, getProductPricing } from './money-price/money-price-config-util.mjs';
|
|
12
|
+
export { UserState } from './money-price/money-price-types.mjs';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var coseBase$1 = require('../../../../../_virtual/cose-
|
|
3
|
+
var coseBase$1 = require('../../../../../_virtual/cose-base.js');
|
|
4
4
|
var layoutBase = require('../../../layout-base@1.0.2/node_modules/layout-base/layout-base.js');
|
|
5
5
|
|
|
6
6
|
var coseBase = coseBase$1.__module.exports;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __module as coseBase$1 } from '../../../../../_virtual/cose-
|
|
1
|
+
import { __module as coseBase$1 } from '../../../../../_virtual/cose-base2.mjs';
|
|
2
2
|
import { __require as requireLayoutBase } from '../../../layout-base@1.0.2/node_modules/layout-base/layout-base.mjs';
|
|
3
3
|
|
|
4
4
|
var coseBase = coseBase$1.exports;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var coseBase$1 = require('../../../../../_virtual/cose-
|
|
3
|
+
var coseBase$1 = require('../../../../../_virtual/cose-base2.js');
|
|
4
4
|
var layoutBase = require('../../../layout-base@2.0.1/node_modules/layout-base/layout-base.js');
|
|
5
5
|
|
|
6
6
|
var coseBase = coseBase$1.__module.exports;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __module as coseBase$1 } from '../../../../../_virtual/cose-
|
|
1
|
+
import { __module as coseBase$1 } from '../../../../../_virtual/cose-base.mjs';
|
|
2
2
|
import { __require as requireLayoutBase } from '../../../layout-base@2.0.1/node_modules/layout-base/layout-base.mjs';
|
|
3
3
|
|
|
4
4
|
var coseBase = coseBase$1.exports;
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import React, { createContext, useContext, useState } from 'react';
|
|
3
|
+
import React, { createContext, useContext, useState, useEffect, useRef } from 'react';
|
|
4
4
|
import { useFingerprint } from './use-fingerprint';
|
|
5
|
+
import { globalLucideIcons as icons } from '@windrun-huaiin/base-ui/components/server';
|
|
5
6
|
import type {
|
|
6
7
|
FingerprintContextType,
|
|
7
8
|
FingerprintProviderProps
|
|
@@ -78,11 +79,35 @@ export function FingerprintStatus() {
|
|
|
78
79
|
} = useFingerprintContext();
|
|
79
80
|
|
|
80
81
|
const [isOpen, setIsOpen] = useState(false);
|
|
82
|
+
const modalRef = useRef<HTMLDivElement>(null);
|
|
81
83
|
|
|
82
84
|
const handleToggle = () => {
|
|
83
85
|
setIsOpen(!isOpen);
|
|
84
86
|
};
|
|
85
87
|
|
|
88
|
+
const handleBackdropClick = (e: React.MouseEvent) => {
|
|
89
|
+
if (e.target === e.currentTarget) {
|
|
90
|
+
setIsOpen(false);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// ESC键关闭弹框
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
const handleEscKey = (e: KeyboardEvent) => {
|
|
97
|
+
if (e.key === 'Escape' && isOpen) {
|
|
98
|
+
setIsOpen(false);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
if (isOpen) {
|
|
103
|
+
document.addEventListener('keydown', handleEscKey);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return () => {
|
|
107
|
+
document.removeEventListener('keydown', handleEscKey);
|
|
108
|
+
};
|
|
109
|
+
}, [isOpen]);
|
|
110
|
+
|
|
86
111
|
return (
|
|
87
112
|
<>
|
|
88
113
|
<button
|
|
@@ -104,17 +129,20 @@ export function FingerprintStatus() {
|
|
|
104
129
|
boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
|
|
105
130
|
}}
|
|
106
131
|
>
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
132
|
+
<icons.BTC
|
|
133
|
+
size={24}
|
|
134
|
+
style={{
|
|
135
|
+
color: 'white',
|
|
136
|
+
transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',
|
|
137
|
+
transition: 'transform 0.3s ease',
|
|
138
|
+
}}
|
|
139
|
+
/>
|
|
113
140
|
</button>
|
|
114
141
|
|
|
115
142
|
{isOpen && (
|
|
116
143
|
<>
|
|
117
144
|
<div
|
|
145
|
+
onClick={handleBackdropClick}
|
|
118
146
|
style={{
|
|
119
147
|
position: 'fixed',
|
|
120
148
|
top: 0,
|
|
@@ -126,6 +154,7 @@ export function FingerprintStatus() {
|
|
|
126
154
|
}}
|
|
127
155
|
/>
|
|
128
156
|
<div
|
|
157
|
+
ref={modalRef}
|
|
129
158
|
style={{
|
|
130
159
|
position: 'fixed',
|
|
131
160
|
top: '70px',
|
|
@@ -135,7 +164,7 @@ export function FingerprintStatus() {
|
|
|
135
164
|
borderRadius: '5px',
|
|
136
165
|
fontSize: '12px',
|
|
137
166
|
fontFamily: 'monospace',
|
|
138
|
-
maxWidth: '
|
|
167
|
+
maxWidth: '500px',
|
|
139
168
|
zIndex: 9999,
|
|
140
169
|
border: '1px solid #ccc',
|
|
141
170
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.2)',
|
|
@@ -158,18 +187,22 @@ export function FingerprintStatus() {
|
|
|
158
187
|
<strong>Credits:</strong> {xCredit.balanceFree} Free + {xCredit.balancePaid} Paid = {xCredit.totalBalance} Total
|
|
159
188
|
</div>
|
|
160
189
|
)}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
190
|
+
<div>
|
|
191
|
+
{xSubscription ? (
|
|
192
|
+
<>
|
|
193
|
+
<strong>user_id:</strong> {xSubscription.userId} <br/>
|
|
194
|
+
<strong>pay_subscription_id:</strong> {xSubscription.paySubscriptionId} <br/>
|
|
195
|
+
<strong>price_id:</strong> {xSubscription.priceId || 'None'} <br/>
|
|
196
|
+
<strong>price_name:</strong> {xSubscription.priceName || 'None'} <br/>
|
|
197
|
+
<strong>status:</strong> {xSubscription.status || 'Free'} <br/>
|
|
198
|
+
<strong>credits_allocated:</strong> {xSubscription.creditsAllocated || ''} <br/>
|
|
199
|
+
<strong>sub_period_start:</strong> {xSubscription.subPeriodStart || ''} <br/>
|
|
200
|
+
<strong>sub_period_end:</strong> {xSubscription.subPeriodEnd || ''} <br/>
|
|
201
|
+
</>
|
|
202
|
+
) : (
|
|
203
|
+
<strong>No Subscription, Default as Hobby Plan</strong>
|
|
204
|
+
)}
|
|
205
|
+
</div>
|
|
173
206
|
</div>
|
|
174
207
|
</>
|
|
175
208
|
)}
|