@windrun-huaiin/third-ui 7.3.3 → 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.
Files changed (32) hide show
  1. package/dist/clerk/fingerprint/fingerprint-provider.js +26 -6
  2. package/dist/clerk/fingerprint/fingerprint-provider.mjs +27 -7
  3. package/dist/clerk/fingerprint/use-fingerprint.js +1 -1
  4. package/dist/clerk/fingerprint/use-fingerprint.mjs +1 -1
  5. package/dist/main/faq.js +0 -1
  6. package/dist/main/faq.mjs +0 -1
  7. package/dist/main/gallery.js +0 -1
  8. package/dist/main/gallery.mjs +0 -1
  9. package/dist/main/money-price/money-price-config-util.d.ts +7 -0
  10. package/dist/main/money-price/money-price-config-util.js +19 -0
  11. package/dist/main/money-price/money-price-config-util.mjs +16 -0
  12. package/dist/main/money-price/money-price-interactive.js +28 -6
  13. package/dist/main/money-price/money-price-interactive.mjs +26 -4
  14. package/dist/main/money-price/money-price-types.d.ts +1 -1
  15. package/dist/main/money-price/money-price.js +2 -2
  16. package/dist/main/money-price/money-price.mjs +1 -1
  17. package/dist/main/price-plan.js +0 -1
  18. package/dist/main/price-plan.mjs +0 -1
  19. package/dist/main/server.d.ts +1 -1
  20. package/dist/main/server.js +3 -4
  21. package/dist/main/server.mjs +1 -1
  22. package/dist/node_modules/.pnpm/cose-base@1.0.3/node_modules/cose-base/cose-base.mjs +1 -1
  23. package/dist/node_modules/.pnpm/cose-base@2.2.0/node_modules/cose-base/cose-base.mjs +1 -1
  24. package/package.json +1 -1
  25. package/src/clerk/fingerprint/fingerprint-provider.tsx +53 -20
  26. package/src/clerk/fingerprint/use-fingerprint.ts +1 -1
  27. package/src/main/money-price/money-price-config-util.ts +23 -0
  28. package/src/main/money-price/money-price-interactive.tsx +28 -3
  29. package/src/main/money-price/money-price-types.ts +1 -1
  30. package/src/main/money-price/money-price.tsx +1 -1
  31. package/src/main/server.ts +1 -2
  32. package/src/main/money-price/money-price-config.ts +0 -229
@@ -4,6 +4,7 @@
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var React = require('react');
6
6
  var useFingerprint = require('./use-fingerprint.js');
7
+ var server = require('@windrun-huaiin/base-ui/components/server');
7
8
 
8
9
  const FingerprintContext = React.createContext(undefined);
9
10
  /**
@@ -47,9 +48,29 @@ function withFingerprint(Component, config) {
47
48
  function FingerprintStatus() {
48
49
  const { fingerprintId, xUser, xCredit, xSubscription, isLoading, isInitialized, error } = useFingerprintContext();
49
50
  const [isOpen, setIsOpen] = React.useState(false);
51
+ const modalRef = React.useRef(null);
50
52
  const handleToggle = () => {
51
53
  setIsOpen(!isOpen);
52
54
  };
55
+ const handleBackdropClick = (e) => {
56
+ if (e.target === e.currentTarget) {
57
+ setIsOpen(false);
58
+ }
59
+ };
60
+ // ESC键关闭弹框
61
+ React.useEffect(() => {
62
+ const handleEscKey = (e) => {
63
+ if (e.key === 'Escape' && isOpen) {
64
+ setIsOpen(false);
65
+ }
66
+ };
67
+ if (isOpen) {
68
+ document.addEventListener('keydown', handleEscKey);
69
+ }
70
+ return () => {
71
+ document.removeEventListener('keydown', handleEscKey);
72
+ };
73
+ }, [isOpen]);
53
74
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { onClick: handleToggle, style: {
54
75
  position: 'fixed',
55
76
  top: '10px',
@@ -65,12 +86,11 @@ function FingerprintStatus() {
65
86
  alignItems: 'center',
66
87
  justifyContent: 'center',
67
88
  boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
68
- }, children: jsxRuntime.jsx("span", { style: {
69
- fontSize: '24px',
89
+ }, children: jsxRuntime.jsx(server.globalLucideIcons.BTC, { size: 24, style: {
70
90
  color: 'white',
71
91
  transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',
72
92
  transition: 'transform 0.3s ease',
73
- }, children: "\u25BC" }) }), isOpen && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { style: {
93
+ } }) }), isOpen && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { onClick: handleBackdropClick, style: {
74
94
  position: 'fixed',
75
95
  top: 0,
76
96
  left: 0,
@@ -78,7 +98,7 @@ function FingerprintStatus() {
78
98
  height: '100%',
79
99
  background: 'rgba(0, 0, 0, 0.5)',
80
100
  zIndex: 9998,
81
- } }), jsxRuntime.jsxs("div", { style: {
101
+ } }), jsxRuntime.jsxs("div", { ref: modalRef, style: {
82
102
  position: 'fixed',
83
103
  top: '70px',
84
104
  left: '10px',
@@ -87,11 +107,11 @@ function FingerprintStatus() {
87
107
  borderRadius: '5px',
88
108
  fontSize: '12px',
89
109
  fontFamily: 'monospace',
90
- maxWidth: '300px',
110
+ maxWidth: '500px',
91
111
  zIndex: 9999,
92
112
  border: '1px solid #ccc',
93
113
  boxShadow: '0 4px 12px rgba(0, 0, 0, 0.2)',
94
- }, children: [jsxRuntime.jsx("h4", { style: { margin: '0 0 5px 0' }, children: "Fingerprint Debug" }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "FP_ID:" }), " ", fingerprintId || 'None'] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Loading:" }), " ", isLoading ? 'Yes' : 'No'] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Initialized:" }), " ", isInitialized ? 'Yes' : 'No'] }), error && jsxRuntime.jsxs("div", { style: { color: 'red' }, children: [jsxRuntime.jsx("strong", { children: "Error:" }), " ", error] }), xUser && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "user_id:" }), " ", xUser.userId, " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "clerk_user_id:" }), " ", xUser.clerkUserId || 'None', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "email:" }), " ", xUser.email || 'None', " ", jsxRuntime.jsx("br", {})] })), xCredit && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Credits:" }), " ", xCredit.balanceFree, " Free + ", xCredit.balancePaid, " Paid = ", xCredit.totalBalance, " Total"] })), xSubscription && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "user_id:" }), " ", xSubscription.userId, " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "pay_subscription_id:" }), " ", xSubscription.paySubscriptionId, " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "price_id:" }), " ", xSubscription.priceId || 'None', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "price_name:" }), " ", xSubscription.priceName || 'None', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "status:" }), " ", xSubscription.status || 'Free', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "credits_allocated:" }), " ", xSubscription.creditsAllocated || '', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "sub_period_start:" }), " ", xSubscription.subPeriodStart || '', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "sub_period_end:" }), " ", xSubscription.subPeriodEnd || '', " ", jsxRuntime.jsx("br", {})] }))] })] }))] }));
114
+ }, children: [jsxRuntime.jsx("h4", { style: { margin: '0 0 5px 0' }, children: "Fingerprint Debug" }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "FP_ID:" }), " ", fingerprintId || 'None'] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Loading:" }), " ", isLoading ? 'Yes' : 'No'] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Initialized:" }), " ", isInitialized ? 'Yes' : 'No'] }), error && jsxRuntime.jsxs("div", { style: { color: 'red' }, children: [jsxRuntime.jsx("strong", { children: "Error:" }), " ", error] }), xUser && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "user_id:" }), " ", xUser.userId, " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "clerk_user_id:" }), " ", xUser.clerkUserId || 'None', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "email:" }), " ", xUser.email || 'None', " ", jsxRuntime.jsx("br", {})] })), xCredit && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Credits:" }), " ", xCredit.balanceFree, " Free + ", xCredit.balancePaid, " Paid = ", xCredit.totalBalance, " Total"] })), jsxRuntime.jsx("div", { children: xSubscription ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("strong", { children: "user_id:" }), " ", xSubscription.userId, " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "pay_subscription_id:" }), " ", xSubscription.paySubscriptionId, " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "price_id:" }), " ", xSubscription.priceId || 'None', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "price_name:" }), " ", xSubscription.priceName || 'None', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "status:" }), " ", xSubscription.status || 'Free', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "credits_allocated:" }), " ", xSubscription.creditsAllocated || '', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "sub_period_start:" }), " ", xSubscription.subPeriodStart || '', " ", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("strong", { children: "sub_period_end:" }), " ", xSubscription.subPeriodEnd || '', " ", jsxRuntime.jsx("br", {})] })) : (jsxRuntime.jsx("strong", { children: "No Subscription, Default as Hobby Plan" })) })] })] }))] }));
95
115
  }
96
116
 
97
117
  exports.FingerprintProvider = FingerprintProvider;
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
- import { createContext, useContext, useState } from 'react';
3
+ import { createContext, useContext, useState, useRef, useEffect } from 'react';
4
4
  import { useFingerprint } from './use-fingerprint.mjs';
5
+ import { globalLucideIcons } from '@windrun-huaiin/base-ui/components/server';
5
6
 
6
7
  const FingerprintContext = createContext(undefined);
7
8
  /**
@@ -45,9 +46,29 @@ function withFingerprint(Component, config) {
45
46
  function FingerprintStatus() {
46
47
  const { fingerprintId, xUser, xCredit, xSubscription, isLoading, isInitialized, error } = useFingerprintContext();
47
48
  const [isOpen, setIsOpen] = useState(false);
49
+ const modalRef = useRef(null);
48
50
  const handleToggle = () => {
49
51
  setIsOpen(!isOpen);
50
52
  };
53
+ const handleBackdropClick = (e) => {
54
+ if (e.target === e.currentTarget) {
55
+ setIsOpen(false);
56
+ }
57
+ };
58
+ // ESC键关闭弹框
59
+ useEffect(() => {
60
+ const handleEscKey = (e) => {
61
+ if (e.key === 'Escape' && isOpen) {
62
+ setIsOpen(false);
63
+ }
64
+ };
65
+ if (isOpen) {
66
+ document.addEventListener('keydown', handleEscKey);
67
+ }
68
+ return () => {
69
+ document.removeEventListener('keydown', handleEscKey);
70
+ };
71
+ }, [isOpen]);
51
72
  return (jsxs(Fragment, { children: [jsx("button", { onClick: handleToggle, style: {
52
73
  position: 'fixed',
53
74
  top: '10px',
@@ -63,12 +84,11 @@ function FingerprintStatus() {
63
84
  alignItems: 'center',
64
85
  justifyContent: 'center',
65
86
  boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
66
- }, children: jsx("span", { style: {
67
- fontSize: '24px',
87
+ }, children: jsx(globalLucideIcons.BTC, { size: 24, style: {
68
88
  color: 'white',
69
89
  transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',
70
90
  transition: 'transform 0.3s ease',
71
- }, children: "\u25BC" }) }), isOpen && (jsxs(Fragment, { children: [jsx("div", { style: {
91
+ } }) }), isOpen && (jsxs(Fragment, { children: [jsx("div", { onClick: handleBackdropClick, style: {
72
92
  position: 'fixed',
73
93
  top: 0,
74
94
  left: 0,
@@ -76,7 +96,7 @@ function FingerprintStatus() {
76
96
  height: '100%',
77
97
  background: 'rgba(0, 0, 0, 0.5)',
78
98
  zIndex: 9998,
79
- } }), jsxs("div", { style: {
99
+ } }), jsxs("div", { ref: modalRef, style: {
80
100
  position: 'fixed',
81
101
  top: '70px',
82
102
  left: '10px',
@@ -85,11 +105,11 @@ function FingerprintStatus() {
85
105
  borderRadius: '5px',
86
106
  fontSize: '12px',
87
107
  fontFamily: 'monospace',
88
- maxWidth: '300px',
108
+ maxWidth: '500px',
89
109
  zIndex: 9999,
90
110
  border: '1px solid #ccc',
91
111
  boxShadow: '0 4px 12px rgba(0, 0, 0, 0.2)',
92
- }, children: [jsx("h4", { style: { margin: '0 0 5px 0' }, children: "Fingerprint Debug" }), jsxs("div", { children: [jsx("strong", { children: "FP_ID:" }), " ", fingerprintId || 'None'] }), jsxs("div", { children: [jsx("strong", { children: "Loading:" }), " ", isLoading ? 'Yes' : 'No'] }), jsxs("div", { children: [jsx("strong", { children: "Initialized:" }), " ", isInitialized ? 'Yes' : 'No'] }), error && jsxs("div", { style: { color: 'red' }, children: [jsx("strong", { children: "Error:" }), " ", error] }), xUser && (jsxs("div", { children: [jsx("strong", { children: "user_id:" }), " ", xUser.userId, " ", jsx("br", {}), jsx("strong", { children: "clerk_user_id:" }), " ", xUser.clerkUserId || 'None', " ", jsx("br", {}), jsx("strong", { children: "email:" }), " ", xUser.email || 'None', " ", jsx("br", {})] })), xCredit && (jsxs("div", { children: [jsx("strong", { children: "Credits:" }), " ", xCredit.balanceFree, " Free + ", xCredit.balancePaid, " Paid = ", xCredit.totalBalance, " Total"] })), xSubscription && (jsxs("div", { children: [jsx("strong", { children: "user_id:" }), " ", xSubscription.userId, " ", jsx("br", {}), jsx("strong", { children: "pay_subscription_id:" }), " ", xSubscription.paySubscriptionId, " ", jsx("br", {}), jsx("strong", { children: "price_id:" }), " ", xSubscription.priceId || 'None', " ", jsx("br", {}), jsx("strong", { children: "price_name:" }), " ", xSubscription.priceName || 'None', " ", jsx("br", {}), jsx("strong", { children: "status:" }), " ", xSubscription.status || 'Free', " ", jsx("br", {}), jsx("strong", { children: "credits_allocated:" }), " ", xSubscription.creditsAllocated || '', " ", jsx("br", {}), jsx("strong", { children: "sub_period_start:" }), " ", xSubscription.subPeriodStart || '', " ", jsx("br", {}), jsx("strong", { children: "sub_period_end:" }), " ", xSubscription.subPeriodEnd || '', " ", jsx("br", {})] }))] })] }))] }));
112
+ }, children: [jsx("h4", { style: { margin: '0 0 5px 0' }, children: "Fingerprint Debug" }), jsxs("div", { children: [jsx("strong", { children: "FP_ID:" }), " ", fingerprintId || 'None'] }), jsxs("div", { children: [jsx("strong", { children: "Loading:" }), " ", isLoading ? 'Yes' : 'No'] }), jsxs("div", { children: [jsx("strong", { children: "Initialized:" }), " ", isInitialized ? 'Yes' : 'No'] }), error && jsxs("div", { style: { color: 'red' }, children: [jsx("strong", { children: "Error:" }), " ", error] }), xUser && (jsxs("div", { children: [jsx("strong", { children: "user_id:" }), " ", xUser.userId, " ", jsx("br", {}), jsx("strong", { children: "clerk_user_id:" }), " ", xUser.clerkUserId || 'None', " ", jsx("br", {}), jsx("strong", { children: "email:" }), " ", xUser.email || 'None', " ", jsx("br", {})] })), xCredit && (jsxs("div", { children: [jsx("strong", { children: "Credits:" }), " ", xCredit.balanceFree, " Free + ", xCredit.balancePaid, " Paid = ", xCredit.totalBalance, " Total"] })), jsx("div", { children: xSubscription ? (jsxs(Fragment, { children: [jsx("strong", { children: "user_id:" }), " ", xSubscription.userId, " ", jsx("br", {}), jsx("strong", { children: "pay_subscription_id:" }), " ", xSubscription.paySubscriptionId, " ", jsx("br", {}), jsx("strong", { children: "price_id:" }), " ", xSubscription.priceId || 'None', " ", jsx("br", {}), jsx("strong", { children: "price_name:" }), " ", xSubscription.priceName || 'None', " ", jsx("br", {}), jsx("strong", { children: "status:" }), " ", xSubscription.status || 'Free', " ", jsx("br", {}), jsx("strong", { children: "credits_allocated:" }), " ", xSubscription.creditsAllocated || '', " ", jsx("br", {}), jsx("strong", { children: "sub_period_start:" }), " ", xSubscription.subPeriodStart || '', " ", jsx("br", {}), jsx("strong", { children: "sub_period_end:" }), " ", xSubscription.subPeriodEnd || '', " ", jsx("br", {})] })) : (jsx("strong", { children: "No Subscription, Default as Hobby Plan" })) })] })] }))] }));
93
113
  }
94
114
 
95
115
  export { FingerprintProvider, FingerprintStatus, useFingerprintContext, useFingerprintContextSafe, withFingerprint };
@@ -81,7 +81,7 @@ function useFingerprint(config) {
81
81
  finally {
82
82
  setIsLoading(false);
83
83
  }
84
- }), [fingerprintId]);
84
+ }), [fingerprintId, config.apiEndpoint]);
85
85
  /**
86
86
  * 刷新用户数据
87
87
  */
@@ -79,7 +79,7 @@ function useFingerprint(config) {
79
79
  finally {
80
80
  setIsLoading(false);
81
81
  }
82
- }), [fingerprintId]);
82
+ }), [fingerprintId, config.apiEndpoint]);
83
83
  /**
84
84
  * 刷新用户数据
85
85
  */
package/dist/main/faq.js CHANGED
@@ -23,7 +23,6 @@ require('fumadocs-core/link');
23
23
  require('fumadocs-ui/components/ui/collapsible');
24
24
  require('../fuma/mdx/banner.js');
25
25
  require('./money-price/money-price-types.js');
26
- require('./money-price/money-price-config.js');
27
26
 
28
27
  function FAQ(_a) {
29
28
  return tslib_es6.__awaiter(this, arguments, void 0, function* ({ locale, sectionClassName }) {
package/dist/main/faq.mjs CHANGED
@@ -21,7 +21,6 @@ import 'fumadocs-core/link';
21
21
  import 'fumadocs-ui/components/ui/collapsible';
22
22
  import '../fuma/mdx/banner.mjs';
23
23
  import './money-price/money-price-types.mjs';
24
- import './money-price/money-price-config.mjs';
25
24
 
26
25
  function FAQ(_a) {
27
26
  return __awaiter(this, arguments, void 0, function* ({ locale, sectionClassName }) {
@@ -23,7 +23,6 @@ require('fumadocs-core/link');
23
23
  require('fumadocs-ui/components/ui/collapsible');
24
24
  require('../fuma/mdx/banner.js');
25
25
  require('./money-price/money-price-types.js');
26
- require('./money-price/money-price-config.js');
27
26
 
28
27
  function Gallery(_a) {
29
28
  return tslib_es6.__awaiter(this, arguments, void 0, function* ({ locale, sectionClassName, button }) {
@@ -21,7 +21,6 @@ import 'fumadocs-core/link';
21
21
  import 'fumadocs-ui/components/ui/collapsible';
22
22
  import '../fuma/mdx/banner.mjs';
23
23
  import './money-price/money-price-types.mjs';
24
- import './money-price/money-price-config.mjs';
25
24
 
26
25
  function Gallery(_a) {
27
26
  return __awaiter(this, arguments, void 0, function* ({ locale, sectionClassName, button }) {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Money Price Configuration
3
+ * 价格组件配置文件
4
+ */
5
+ import type { MoneyPriceConfig, PaymentProviderConfig, EnhancePricePlan } from './money-price-types';
6
+ export declare function getActiveProviderConfig(config: MoneyPriceConfig): PaymentProviderConfig;
7
+ export declare function getProductPricing(productKey: 'free' | 'pro' | 'ultra', billingType: 'monthly' | 'yearly', provider: string, config: MoneyPriceConfig): EnhancePricePlan;
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Money Price Configuration
5
+ * 价格组件配置文件
6
+ */
7
+ // 辅助函数:获取当前激活的支付供应商配置
8
+ function getActiveProviderConfig(config) {
9
+ const provider = config.activeProvider;
10
+ return config.paymentProviders[provider];
11
+ }
12
+ // 辅助函数:获取特定产品的价格信息
13
+ function getProductPricing(productKey, billingType, provider, config) {
14
+ const providerConfig = config.paymentProviders[provider];
15
+ return providerConfig.products[productKey].plans[billingType];
16
+ }
17
+
18
+ exports.getActiveProviderConfig = getActiveProviderConfig;
19
+ exports.getProductPricing = getProductPricing;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Money Price Configuration
3
+ * 价格组件配置文件
4
+ */
5
+ // 辅助函数:获取当前激活的支付供应商配置
6
+ function getActiveProviderConfig(config) {
7
+ const provider = config.activeProvider;
8
+ return config.paymentProviders[provider];
9
+ }
10
+ // 辅助函数:获取特定产品的价格信息
11
+ function getProductPricing(productKey, billingType, provider, config) {
12
+ const providerConfig = config.paymentProviders[provider];
13
+ return providerConfig.products[productKey].plans[billingType];
14
+ }
15
+
16
+ export { getActiveProviderConfig, getProductPricing };
@@ -10,7 +10,7 @@ var utils = require('@windrun-huaiin/lib/utils');
10
10
  var navigation = require('next/navigation');
11
11
  var client = require('react-dom/client');
12
12
  var moneyPriceButton = require('./money-price-button.js');
13
- var moneyPriceConfig = require('./money-price-config.js');
13
+ var moneyPriceConfigUtil = require('./money-price-config-util.js');
14
14
  var moneyPriceTypes = require('./money-price-types.js');
15
15
 
16
16
  function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath }) {
@@ -62,7 +62,7 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
62
62
  setIsProcessing(true);
63
63
  try {
64
64
  // 获取价格配置
65
- const pricing = moneyPriceConfig.getProductPricing(plan, billingType, config.activeProvider, config);
65
+ const pricing = moneyPriceConfigUtil.getProductPricing(plan, billingType, config.activeProvider, config);
66
66
  // 调用 API 创建支付会话
67
67
  const response = yield fetch(upgradeApiEndpoint, {
68
68
  method: 'POST',
@@ -94,7 +94,7 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
94
94
  });
95
95
  // 更新价格显示
96
96
  const updatePriceDisplay = (newBillingType) => {
97
- const providerConfig = moneyPriceConfig.getActiveProviderConfig(config);
97
+ const providerConfig = moneyPriceConfigUtil.getActiveProviderConfig(config);
98
98
  data.plans.forEach((plan) => {
99
99
  const productConfig = providerConfig.products[plan.key];
100
100
  const pricing = productConfig.plans[newBillingType];
@@ -167,7 +167,7 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
167
167
  if (!discountInfoElement)
168
168
  return;
169
169
  const billingOption = data.billingSwitch.options.find(opt => opt.key === newBillingType);
170
- const providerConfig = moneyPriceConfig.getActiveProviderConfig(config);
170
+ const providerConfig = moneyPriceConfigUtil.getActiveProviderConfig(config);
171
171
  // 检查是否有折扣
172
172
  let hasDiscount = false;
173
173
  let discountPercent = 0;
@@ -188,16 +188,38 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
188
188
  discountInfoElement.appendChild(discountBadge);
189
189
  }
190
190
  };
191
+ // 使用 useRef 存储 root 实例,避免重复创建
192
+ const rootsRef = React.useRef(new Map());
191
193
  // 动态替换按钮
192
194
  React.useEffect(() => {
193
195
  data.plans.forEach((plan) => {
194
196
  const placeholder = document.querySelector(`[data-button-placeholder="${plan.key}"]`);
195
197
  if (placeholder) {
196
- const root = client.createRoot(placeholder);
198
+ let root = rootsRef.current.get(plan.key);
199
+ // 如果还没有创建 root,则创建一个
200
+ if (!root) {
201
+ root = client.createRoot(placeholder);
202
+ rootsRef.current.set(plan.key, root);
203
+ }
204
+ // 渲染按钮
197
205
  root.render(jsxRuntime.jsx(moneyPriceButton.MoneyPriceButton, { planKey: plan.key, userContext: userContext, billingType: billingType, onLogin: handleLogin, onUpgrade: handleUpgrade, texts: data.buttonTexts, isProcessing: isProcessing }));
198
206
  }
199
207
  });
200
- }, [userContext, billingType, isProcessing]);
208
+ }, [userContext, billingType, isProcessing, data.plans, data.buttonTexts, handleLogin, handleUpgrade]);
209
+ // 组件卸载时清理
210
+ React.useEffect(() => {
211
+ return () => {
212
+ rootsRef.current.forEach((root) => {
213
+ try {
214
+ root.unmount();
215
+ }
216
+ catch (e) {
217
+ // 忽略卸载错误
218
+ }
219
+ });
220
+ rootsRef.current.clear();
221
+ };
222
+ }, []);
201
223
  // 处理月付/年付切换和 tooltip 功能
202
224
  React.useEffect(() => {
203
225
  const monthlyButton = document.querySelector('[data-billing-button="monthly"]');
@@ -2,13 +2,13 @@
2
2
  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';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
  import { useClerk } from '@clerk/nextjs';
5
- import { useState, useEffect } from 'react';
5
+ import React, { useState, useEffect } from 'react';
6
6
  import { useFingerprintContextSafe } from '../../clerk/fingerprint/fingerprint-provider.mjs';
7
7
  import { cn } from '@windrun-huaiin/lib/utils';
8
8
  import { useRouter } from 'next/navigation';
9
9
  import { createRoot } from 'react-dom/client';
10
10
  import { MoneyPriceButton } from './money-price-button.mjs';
11
- import { getProductPricing, getActiveProviderConfig } from './money-price-config.mjs';
11
+ import { getProductPricing, getActiveProviderConfig } from './money-price-config-util.mjs';
12
12
  import { UserState } from './money-price-types.mjs';
13
13
 
14
14
  function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath }) {
@@ -186,16 +186,38 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
186
186
  discountInfoElement.appendChild(discountBadge);
187
187
  }
188
188
  };
189
+ // 使用 useRef 存储 root 实例,避免重复创建
190
+ const rootsRef = React.useRef(new Map());
189
191
  // 动态替换按钮
190
192
  useEffect(() => {
191
193
  data.plans.forEach((plan) => {
192
194
  const placeholder = document.querySelector(`[data-button-placeholder="${plan.key}"]`);
193
195
  if (placeholder) {
194
- const root = createRoot(placeholder);
196
+ let root = rootsRef.current.get(plan.key);
197
+ // 如果还没有创建 root,则创建一个
198
+ if (!root) {
199
+ root = createRoot(placeholder);
200
+ rootsRef.current.set(plan.key, root);
201
+ }
202
+ // 渲染按钮
195
203
  root.render(jsx(MoneyPriceButton, { planKey: plan.key, userContext: userContext, billingType: billingType, onLogin: handleLogin, onUpgrade: handleUpgrade, texts: data.buttonTexts, isProcessing: isProcessing }));
196
204
  }
197
205
  });
198
- }, [userContext, billingType, isProcessing]);
206
+ }, [userContext, billingType, isProcessing, data.plans, data.buttonTexts, handleLogin, handleUpgrade]);
207
+ // 组件卸载时清理
208
+ useEffect(() => {
209
+ return () => {
210
+ rootsRef.current.forEach((root) => {
211
+ try {
212
+ root.unmount();
213
+ }
214
+ catch (e) {
215
+ // 忽略卸载错误
216
+ }
217
+ });
218
+ rootsRef.current.clear();
219
+ };
220
+ }, []);
199
221
  // 处理月付/年付切换和 tooltip 功能
200
222
  useEffect(() => {
201
223
  const monthlyButton = document.querySelector('[data-billing-button="monthly"]');
@@ -14,7 +14,7 @@ export interface UserContext {
14
14
  subscriptionType?: 'monthly' | 'yearly';
15
15
  subscriptionEndDate?: string;
16
16
  }
17
- export type PaymentProvider = 'stripe' | 'alipay' | 'wechat' | 'paypal';
17
+ export type PaymentProvider = 'stripe' | 'apple' | 'paypal' | 'wechat' | 'alipay';
18
18
  export interface EnhancePricePlan {
19
19
  priceId: string;
20
20
  amount: number;
@@ -16,7 +16,7 @@ require('@windrun-huaiin/base-ui/ui');
16
16
  require('fumadocs-ui/components/ui/collapsible');
17
17
  require('../../fuma/mdx/banner.js');
18
18
  var server = require('next-intl/server');
19
- var moneyPriceConfig = require('./money-price-config.js');
19
+ var moneyPriceConfigUtil = require('./money-price-config-util.js');
20
20
  var moneyPriceInteractive = require('./money-price-interactive.js');
21
21
 
22
22
  function MoneyPrice(_a) {
@@ -32,7 +32,7 @@ function MoneyPrice(_a) {
32
32
  currency: config.display.currency
33
33
  };
34
34
  // 获取激活的支付供应商配置
35
- const providerConfig = moneyPriceConfig.getActiveProviderConfig(config);
35
+ const providerConfig = moneyPriceConfigUtil.getActiveProviderConfig(config);
36
36
  const minPlanFeaturesCount = config.display.minFeaturesCount;
37
37
  // 使用默认计费类型进行静态渲染
38
38
  const defaultBilling = data.billingSwitch.defaultKey;
@@ -14,7 +14,7 @@ import '@windrun-huaiin/base-ui/ui';
14
14
  import 'fumadocs-ui/components/ui/collapsible';
15
15
  import '../../fuma/mdx/banner.mjs';
16
16
  import { getTranslations } from 'next-intl/server';
17
- import { getActiveProviderConfig } from './money-price-config.mjs';
17
+ import { getActiveProviderConfig } from './money-price-config-util.mjs';
18
18
  import { MoneyPriceInteractive } from './money-price-interactive.mjs';
19
19
 
20
20
  function MoneyPrice(_a) {
@@ -23,7 +23,6 @@ require('fumadocs-core/link');
23
23
  require('fumadocs-ui/components/ui/collapsible');
24
24
  require('../fuma/mdx/banner.js');
25
25
  require('./money-price/money-price-types.js');
26
- require('./money-price/money-price-config.js');
27
26
 
28
27
  function PricePlan(_a) {
29
28
  return tslib_es6.__awaiter(this, arguments, void 0, function* ({ locale, currency = '$', pricePlanConfig, sectionClassName }) {
@@ -21,7 +21,6 @@ import 'fumadocs-core/link';
21
21
  import 'fumadocs-ui/components/ui/collapsible';
22
22
  import '../fuma/mdx/banner.mjs';
23
23
  import './money-price/money-price-types.mjs';
24
- import './money-price/money-price-config.mjs';
25
24
 
26
25
  function PricePlan(_a) {
27
26
  return __awaiter(this, arguments, void 0, function* ({ locale, currency = '$', pricePlanConfig, sectionClassName }) {
@@ -8,6 +8,6 @@ export * from './cta';
8
8
  export * from './footer';
9
9
  export * from './price-plan';
10
10
  export { MoneyPrice } from './money-price/money-price';
11
- export { moneyPriceConfig, getActiveProviderConfig, getProductPricing } from './money-price/money-price-config';
11
+ export { getActiveProviderConfig, getProductPricing } from './money-price/money-price-config-util';
12
12
  export type { MoneyPriceConfig, MoneyPriceProps, MoneyPriceInteractiveProps, MoneyPriceButtonProps, MoneyPriceData, PaymentProvider, PaymentProviderConfig, EnhancePricePlan, ProductConfig, UserContext } from './money-price/money-price-types';
13
13
  export { UserState } from './money-price/money-price-types';
@@ -10,7 +10,7 @@ var cta = require('./cta.js');
10
10
  var footer = require('./footer.js');
11
11
  var pricePlan = require('./price-plan.js');
12
12
  var moneyPrice = require('./money-price/money-price.js');
13
- var moneyPriceConfig = require('./money-price/money-price-config.js');
13
+ var moneyPriceConfigUtil = require('./money-price/money-price-config-util.js');
14
14
  var moneyPriceTypes = require('./money-price/money-price-types.js');
15
15
 
16
16
 
@@ -25,9 +25,8 @@ exports.CTA = cta.CTA;
25
25
  exports.Footer = footer.Footer;
26
26
  exports.PricePlan = pricePlan.PricePlan;
27
27
  exports.MoneyPrice = moneyPrice.MoneyPrice;
28
- exports.getActiveProviderConfig = moneyPriceConfig.getActiveProviderConfig;
29
- exports.getProductPricing = moneyPriceConfig.getProductPricing;
30
- exports.moneyPriceConfig = moneyPriceConfig.moneyPriceConfig;
28
+ exports.getActiveProviderConfig = moneyPriceConfigUtil.getActiveProviderConfig;
29
+ exports.getProductPricing = moneyPriceConfigUtil.getProductPricing;
31
30
  Object.defineProperty(exports, "UserState", {
32
31
  enumerable: true,
33
32
  get: function () { return moneyPriceTypes.UserState; }
@@ -8,5 +8,5 @@ export { CTA } from './cta.mjs';
8
8
  export { Footer } from './footer.mjs';
9
9
  export { PricePlan } from './price-plan.mjs';
10
10
  export { MoneyPrice } from './money-price/money-price.mjs';
11
- export { getActiveProviderConfig, getProductPricing, moneyPriceConfig } from './money-price/money-price-config.mjs';
11
+ export { getActiveProviderConfig, getProductPricing } from './money-price/money-price-config-util.mjs';
12
12
  export { UserState } from './money-price/money-price-types.mjs';
@@ -1,4 +1,4 @@
1
- import { __module as coseBase$1 } from '../../../../../_virtual/cose-base.mjs';
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,4 +1,4 @@
1
- import { __module as coseBase$1 } from '../../../../../_virtual/cose-base2.mjs';
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@windrun-huaiin/third-ui",
3
- "version": "7.3.3",
3
+ "version": "7.3.4",
4
4
  "description": "Third-party integrated UI components for windrun-huaiin projects",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -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
- <span style={{
108
- fontSize: '24px',
109
- color: 'white',
110
- transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',
111
- transition: 'transform 0.3s ease',
112
- }}>▼</span>
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: '300px',
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
- {xSubscription && (
162
- <div>
163
- <strong>user_id:</strong> {xSubscription.userId} <br/>
164
- <strong>pay_subscription_id:</strong> {xSubscription.paySubscriptionId} <br/>
165
- <strong>price_id:</strong> {xSubscription.priceId || 'None'} <br/>
166
- <strong>price_name:</strong> {xSubscription.priceName || 'None'} <br/>
167
- <strong>status:</strong> {xSubscription.status || 'Free'} <br/>
168
- <strong>credits_allocated:</strong> {xSubscription.creditsAllocated || ''} <br/>
169
- <strong>sub_period_start:</strong> {xSubscription.subPeriodStart || ''} <br/>
170
- <strong>sub_period_end:</strong> {xSubscription.subPeriodEnd || ''} <br/>
171
- </div>
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
  )}
@@ -97,7 +97,7 @@ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult
97
97
  } finally {
98
98
  setIsLoading(false);
99
99
  }
100
- }, [fingerprintId]);
100
+ }, [fingerprintId, config.apiEndpoint]);
101
101
 
102
102
  /**
103
103
  * 刷新用户数据
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Money Price Configuration
3
+ * 价格组件配置文件
4
+ */
5
+
6
+ import type { MoneyPriceConfig, PaymentProviderConfig, EnhancePricePlan } from './money-price-types';
7
+
8
+ // 辅助函数:获取当前激活的支付供应商配置
9
+ export function getActiveProviderConfig(config: MoneyPriceConfig): PaymentProviderConfig {
10
+ const provider = config.activeProvider;
11
+ return config.paymentProviders[provider];
12
+ }
13
+
14
+ // 辅助函数:获取特定产品的价格信息
15
+ export function getProductPricing(
16
+ productKey: 'free' | 'pro' | 'ultra',
17
+ billingType: 'monthly' | 'yearly',
18
+ provider: string,
19
+ config: MoneyPriceConfig
20
+ ): EnhancePricePlan {
21
+ const providerConfig = config.paymentProviders[provider];
22
+ return providerConfig.products[productKey].plans[billingType];
23
+ }
@@ -7,7 +7,7 @@ import { useRouter } from 'next/navigation';
7
7
  import React, { useEffect, useState } from 'react';
8
8
  import { createRoot } from 'react-dom/client';
9
9
  import { MoneyPriceButton } from './money-price-button';
10
- import { getActiveProviderConfig, getProductPricing } from './money-price-config';
10
+ import { getActiveProviderConfig, getProductPricing } from './money-price-config-util';
11
11
  import {
12
12
  UserState,
13
13
  type MoneyPriceInteractiveProps,
@@ -218,12 +218,23 @@ export function MoneyPriceInteractive({
218
218
  }
219
219
  };
220
220
 
221
+ // 使用 useRef 存储 root 实例,避免重复创建
222
+ const rootsRef = React.useRef<Map<string, any>>(new Map());
223
+
221
224
  // 动态替换按钮
222
225
  useEffect(() => {
223
226
  data.plans.forEach((plan: any) => {
224
227
  const placeholder = document.querySelector(`[data-button-placeholder="${plan.key}"]`);
225
228
  if (placeholder) {
226
- const root = createRoot(placeholder);
229
+ let root = rootsRef.current.get(plan.key);
230
+
231
+ // 如果还没有创建 root,则创建一个
232
+ if (!root) {
233
+ root = createRoot(placeholder);
234
+ rootsRef.current.set(plan.key, root);
235
+ }
236
+
237
+ // 渲染按钮
227
238
  root.render(
228
239
  <MoneyPriceButton
229
240
  planKey={plan.key}
@@ -237,7 +248,21 @@ export function MoneyPriceInteractive({
237
248
  );
238
249
  }
239
250
  });
240
- }, [userContext, billingType, isProcessing]);
251
+ }, [userContext, billingType, isProcessing, data.plans, data.buttonTexts, handleLogin, handleUpgrade]);
252
+
253
+ // 组件卸载时清理
254
+ useEffect(() => {
255
+ return () => {
256
+ rootsRef.current.forEach((root) => {
257
+ try {
258
+ root.unmount();
259
+ } catch (e) {
260
+ // 忽略卸载错误
261
+ }
262
+ });
263
+ rootsRef.current.clear();
264
+ };
265
+ }, []);
241
266
 
242
267
  // 处理月付/年付切换和 tooltip 功能
243
268
  useEffect(() => {
@@ -20,7 +20,7 @@ export interface UserContext {
20
20
  }
21
21
 
22
22
  // 支付供应商类型
23
- export type PaymentProvider = 'stripe' | 'alipay' | 'wechat' | 'paypal';
23
+ export type PaymentProvider = 'stripe' | 'apple' | 'paypal' | 'wechat' | 'alipay' ;
24
24
 
25
25
  // 价格计划
26
26
  export interface EnhancePricePlan {
@@ -2,7 +2,7 @@
2
2
  import { GradientButton } from '@third-ui/fuma/mdx';
3
3
  import { cn } from '@windrun-huaiin/lib/utils';
4
4
  import { getTranslations } from 'next-intl/server';
5
- import { getActiveProviderConfig } from './money-price-config';
5
+ import { getActiveProviderConfig } from './money-price-config-util';
6
6
  import { MoneyPriceInteractive } from './money-price-interactive';
7
7
  import type { MoneyPriceData, MoneyPriceProps } from './money-price-types';
8
8
 
@@ -12,10 +12,9 @@ export * from './price-plan';
12
12
  // Money Price Server Component and Types
13
13
  export { MoneyPrice } from './money-price/money-price';
14
14
  export {
15
- moneyPriceConfig,
16
15
  getActiveProviderConfig,
17
16
  getProductPricing
18
- } from './money-price/money-price-config';
17
+ } from './money-price/money-price-config-util';
19
18
 
20
19
  // Money Price Types (shared between server and client)
21
20
  export type {
@@ -1,229 +0,0 @@
1
- /**
2
- * Money Price Configuration
3
- * 价格组件配置文件
4
- */
5
-
6
- import type { MoneyPriceConfig, PaymentProviderConfig, EnhancePricePlan } from './money-price-types';
7
-
8
- // 示例配置
9
- export const moneyPriceConfig: MoneyPriceConfig = {
10
- paymentProviders: {
11
- stripe: {
12
- provider: 'stripe',
13
- enabled: true,
14
- products: {
15
- free: {
16
- key: 'free',
17
- name: 'free', // Just a key, actual display name comes from translation
18
- plans: {
19
- monthly: {
20
- priceId: 'free',
21
- amount: 0,
22
- currency: 'usd',
23
- credits: 0
24
- },
25
- yearly: {
26
- priceId: 'free',
27
- amount: 0,
28
- currency: 'usd',
29
- credits: 0
30
- }
31
- }
32
- },
33
- pro: {
34
- key: 'pro',
35
- name: 'pro', // Just a key, actual display name comes from translation
36
- plans: {
37
- monthly: {
38
- priceId: process.env.NEXT_PUBLIC_STRIPE_PRO_MONTHLY_PRICE_ID || 'price_pro_monthly',
39
- amount: Number(process.env.NEXT_PUBLIC_STRIPE_PRO_MONTHLY_AMOUNT) || 10,
40
- currency: process.env.NEXT_PUBLIC_STRIPE_PRO_MONTHLY_CURRENCY || 'usd',
41
- credits: Number(process.env.NEXT_PUBLIC_STRIPE_PRO_MONTHLY_CREDITS) || 100
42
- },
43
- yearly: {
44
- priceId: process.env.NEXT_PUBLIC_STRIPE_PRO_YEARLY_PRICE_ID || 'price_pro_yearly',
45
- amount: Number(process.env.NEXT_PUBLIC_STRIPE_PRO_YEARLY_AMOUNT) || 96,
46
- originalAmount: 120,
47
- discountPercent: 20,
48
- currency: process.env.NEXT_PUBLIC_STRIPE_PRO_YEARLY_CURRENCY || 'usd',
49
- credits: Number(process.env.NEXT_PUBLIC_STRIPE_PRO_YEARLY_CREDITS) || 1200
50
- }
51
- }
52
- },
53
- ultra: {
54
- key: 'ultra',
55
- name: 'ultra', // Just a key, actual display name comes from translation
56
- plans: {
57
- monthly: {
58
- priceId: process.env.NEXT_PUBLIC_STRIPE_ULTRA_MONTHLY_PRICE_ID || 'price_ultra_monthly',
59
- amount: Number(process.env.NEXT_PUBLIC_STRIPE_ULTRA_MONTHLY_AMOUNT) || 20,
60
- currency: process.env.NEXT_PUBLIC_STRIPE_ULTRA_MONTHLY_CURRENCY || 'usd',
61
- credits: Number(process.env.NEXT_PUBLIC_STRIPE_ULTRA_MONTHLY_CREDITS) || 250
62
- },
63
- yearly: {
64
- priceId: process.env.NEXT_PUBLIC_STRIPE_ULTRA_YEARLY_PRICE_ID || 'price_ultra_yearly',
65
- amount: Number(process.env.NEXT_PUBLIC_STRIPE_ULTRA_YEARLY_AMOUNT) || 192,
66
- originalAmount: 240,
67
- discountPercent: 20,
68
- currency: process.env.NEXT_PUBLIC_STRIPE_ULTRA_YEARLY_CURRENCY || 'usd',
69
- credits: Number(process.env.NEXT_PUBLIC_STRIPE_ULTRA_YEARLY_CREDITS) || 3000
70
- }
71
- }
72
- }
73
- }
74
- },
75
- alipay: {
76
- provider: 'alipay',
77
- enabled: false,
78
- products: {
79
- free: {
80
- key: 'free',
81
- name: 'free',
82
- plans: {
83
- monthly: {
84
- priceId: 'free',
85
- amount: 0,
86
- currency: 'cny',
87
- credits: 0
88
- },
89
- yearly: {
90
- priceId: 'free',
91
- amount: 0,
92
- currency: 'cny',
93
- credits: 0
94
- }
95
- }
96
- },
97
- pro: {
98
- key: 'pro',
99
- name: 'pro',
100
- plans: {
101
- monthly: {
102
- priceId: 'alipay_pro_monthly',
103
- amount: 70,
104
- currency: 'cny',
105
- credits: 100
106
- },
107
- yearly: {
108
- priceId: 'alipay_pro_yearly',
109
- amount: 672,
110
- originalAmount: 840,
111
- discountPercent: 20,
112
- currency: 'cny',
113
- credits: 1200
114
- }
115
- }
116
- },
117
- ultra: {
118
- key: 'ultra',
119
- name: 'ultra',
120
- plans: {
121
- monthly: {
122
- priceId: 'alipay_ultra_monthly',
123
- amount: 140,
124
- currency: 'cny',
125
- credits: 250
126
- },
127
- yearly: {
128
- priceId: 'alipay_ultra_yearly',
129
- amount: 1344,
130
- originalAmount: 1680,
131
- discountPercent: 20,
132
- currency: 'cny',
133
- credits: 3000
134
- }
135
- }
136
- }
137
- }
138
- },
139
- wechat: {
140
- provider: 'wechat',
141
- enabled: false,
142
- products: {
143
- free: {
144
- key: 'free',
145
- name: 'free',
146
- plans: {
147
- monthly: {
148
- priceId: 'free',
149
- amount: 0,
150
- currency: 'cny',
151
- credits: 0
152
- },
153
- yearly: {
154
- priceId: 'free',
155
- amount: 0,
156
- currency: 'cny',
157
- credits: 0
158
- }
159
- }
160
- },
161
- pro: {
162
- key: 'pro',
163
- name: 'pro',
164
- plans: {
165
- monthly: {
166
- priceId: 'wechat_pro_monthly',
167
- amount: 70,
168
- currency: 'cny',
169
- credits: 100
170
- },
171
- yearly: {
172
- priceId: 'wechat_pro_yearly',
173
- amount: 672,
174
- originalAmount: 840,
175
- discountPercent: 20,
176
- currency: 'cny',
177
- credits: 1200
178
- }
179
- }
180
- },
181
- ultra: {
182
- key: 'ultra',
183
- name: 'ultra',
184
- plans: {
185
- monthly: {
186
- priceId: 'wechat_ultra_monthly',
187
- amount: 140,
188
- currency: 'cny',
189
- credits: 250
190
- },
191
- yearly: {
192
- priceId: 'wechat_ultra_yearly',
193
- amount: 1344,
194
- originalAmount: 1680,
195
- discountPercent: 20,
196
- currency: 'cny',
197
- credits: 3000
198
- }
199
- }
200
- }
201
- }
202
- }
203
- },
204
-
205
- activeProvider: process.env.NEXT_PUBLIC_ACTIVE_PAYMENT_PROVIDER || 'stripe',
206
-
207
- display: {
208
- currency: '$',
209
- locale: 'en',
210
- minFeaturesCount: 4
211
- }
212
- };
213
-
214
- // 辅助函数:获取当前激活的支付供应商配置
215
- export function getActiveProviderConfig(config: MoneyPriceConfig): PaymentProviderConfig {
216
- const provider = config.activeProvider;
217
- return config.paymentProviders[provider];
218
- }
219
-
220
- // 辅助函数:获取特定产品的价格信息
221
- export function getProductPricing(
222
- productKey: 'free' | 'pro' | 'ultra',
223
- billingType: 'monthly' | 'yearly',
224
- provider: string,
225
- config: MoneyPriceConfig
226
- ): EnhancePricePlan {
227
- const providerConfig = config.paymentProviders[provider];
228
- return providerConfig.products[productKey].plans[billingType];
229
- }