@windrun-huaiin/third-ui 7.3.3 → 7.3.5

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 (30) 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 -2
  6. package/dist/main/faq.mjs +0 -2
  7. package/dist/main/gallery.js +0 -2
  8. package/dist/main/gallery.mjs +0 -2
  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 +29 -50
  13. package/dist/main/money-price/money-price-interactive.mjs +28 -49
  14. package/dist/main/money-price/money-price-types.d.ts +1 -1
  15. package/dist/main/money-price/money-price.js +3 -23
  16. package/dist/main/money-price/money-price.mjs +2 -22
  17. package/dist/main/price-plan.js +0 -2
  18. package/dist/main/price-plan.mjs +0 -2
  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/package.json +1 -1
  23. package/src/clerk/fingerprint/fingerprint-provider.tsx +53 -20
  24. package/src/clerk/fingerprint/use-fingerprint.ts +1 -1
  25. package/src/main/money-price/money-price-config-util.ts +23 -0
  26. package/src/main/money-price/money-price-interactive.tsx +47 -64
  27. package/src/main/money-price/money-price-types.ts +1 -1
  28. package/src/main/money-price/money-price.tsx +5 -32
  29. package/src/main/server.ts +1 -2
  30. 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
@@ -14,7 +14,6 @@ var faqInteractive = require('./faq-interactive.js');
14
14
  require('next/navigation');
15
15
  require('@clerk/nextjs');
16
16
  require('../clerk/fingerprint/fingerprint-provider.js');
17
- require('react-dom/client');
18
17
  require('next-themes');
19
18
  require('fumadocs-core/framework');
20
19
  require('next/link');
@@ -23,7 +22,6 @@ require('fumadocs-core/link');
23
22
  require('fumadocs-ui/components/ui/collapsible');
24
23
  require('../fuma/mdx/banner.js');
25
24
  require('./money-price/money-price-types.js');
26
- require('./money-price/money-price-config.js');
27
25
 
28
26
  function FAQ(_a) {
29
27
  return tslib_es6.__awaiter(this, arguments, void 0, function* ({ locale, sectionClassName }) {
package/dist/main/faq.mjs CHANGED
@@ -12,7 +12,6 @@ import { FAQInteractive } from './faq-interactive.mjs';
12
12
  import 'next/navigation';
13
13
  import '@clerk/nextjs';
14
14
  import '../clerk/fingerprint/fingerprint-provider.mjs';
15
- import 'react-dom/client';
16
15
  import 'next-themes';
17
16
  import 'fumadocs-core/framework';
18
17
  import 'next/link';
@@ -21,7 +20,6 @@ import 'fumadocs-core/link';
21
20
  import 'fumadocs-ui/components/ui/collapsible';
22
21
  import '../fuma/mdx/banner.mjs';
23
22
  import './money-price/money-price-types.mjs';
24
- import './money-price/money-price-config.mjs';
25
23
 
26
24
  function FAQ(_a) {
27
25
  return __awaiter(this, arguments, void 0, function* ({ locale, sectionClassName }) {
@@ -14,7 +14,6 @@ require('next/navigation');
14
14
  var galleryInteractive = require('./gallery-interactive.js');
15
15
  require('@clerk/nextjs');
16
16
  require('../clerk/fingerprint/fingerprint-provider.js');
17
- require('react-dom/client');
18
17
  require('next-themes');
19
18
  require('fumadocs-core/framework');
20
19
  require('next/link');
@@ -23,7 +22,6 @@ require('fumadocs-core/link');
23
22
  require('fumadocs-ui/components/ui/collapsible');
24
23
  require('../fuma/mdx/banner.js');
25
24
  require('./money-price/money-price-types.js');
26
- require('./money-price/money-price-config.js');
27
25
 
28
26
  function Gallery(_a) {
29
27
  return tslib_es6.__awaiter(this, arguments, void 0, function* ({ locale, sectionClassName, button }) {
@@ -12,7 +12,6 @@ import 'next/navigation';
12
12
  import { GalleryInteractive } from './gallery-interactive.mjs';
13
13
  import '@clerk/nextjs';
14
14
  import '../clerk/fingerprint/fingerprint-provider.mjs';
15
- import 'react-dom/client';
16
15
  import 'next-themes';
17
16
  import 'fumadocs-core/framework';
18
17
  import 'next/link';
@@ -21,7 +20,6 @@ import 'fumadocs-core/link';
21
20
  import 'fumadocs-ui/components/ui/collapsible';
22
21
  import '../fuma/mdx/banner.mjs';
23
22
  import './money-price/money-price-types.mjs';
24
- import './money-price/money-price-config.mjs';
25
23
 
26
24
  function Gallery(_a) {
27
25
  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 };
@@ -8,13 +8,11 @@ var React = require('react');
8
8
  var fingerprintProvider = require('../../clerk/fingerprint/fingerprint-provider.js');
9
9
  var utils = require('@windrun-huaiin/lib/utils');
10
10
  var navigation = require('next/navigation');
11
- var client = require('react-dom/client');
12
11
  var moneyPriceButton = require('./money-price-button.js');
13
- var moneyPriceConfig = require('./money-price-config.js');
12
+ var moneyPriceConfigUtil = require('./money-price-config-util.js');
14
13
  var moneyPriceTypes = require('./money-price-types.js');
15
14
 
16
15
  function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath }) {
17
- var _a, _b, _c, _d;
18
16
  const fingerprintContext = fingerprintProvider.useFingerprintContextSafe();
19
17
  const { redirectToSignIn } = nextjs.useClerk();
20
18
  const router = navigation.useRouter();
@@ -22,7 +20,7 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
22
20
  const [isProcessing, setIsProcessing] = React.useState(false);
23
21
  const [tooltip, setTooltip] = React.useState({ show: false, content: '', x: 0, y: 0 });
24
22
  // 确定用户状态
25
- const getUserState = () => {
23
+ const getUserState = React.useCallback(() => {
26
24
  var _a, _b;
27
25
  if (!fingerprintContext)
28
26
  return moneyPriceTypes.UserState.Anonymous;
@@ -36,34 +34,35 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
36
34
  if ((_b = xSubscription.priceName) === null || _b === void 0 ? void 0 : _b.includes('Ultra'))
37
35
  return moneyPriceTypes.UserState.UltraUser;
38
36
  return moneyPriceTypes.UserState.FreeUser;
39
- };
40
- const userContext = {
41
- isAuthenticated: !!((_a = fingerprintContext === null || fingerprintContext === void 0 ? void 0 : fingerprintContext.xUser) === null || _a === void 0 ? void 0 : _a.clerkUserId),
42
- subscriptionStatus: getUserState(),
43
- subscriptionType: ((_c = (_b = fingerprintContext === null || fingerprintContext === void 0 ? void 0 : fingerprintContext.xSubscription) === null || _b === void 0 ? void 0 : _b.priceId) === null || _c === void 0 ? void 0 : _c.includes('yearly')) ? 'yearly' : 'monthly',
44
- subscriptionEndDate: (_d = fingerprintContext === null || fingerprintContext === void 0 ? void 0 : fingerprintContext.xSubscription) === null || _d === void 0 ? void 0 : _d.subPeriodEnd
45
- };
37
+ }, [fingerprintContext]);
38
+ // 优化 userContext 使用 useMemo
39
+ const userContext = React.useMemo(() => {
40
+ var _a, _b, _c, _d;
41
+ return ({
42
+ isAuthenticated: !!((_a = fingerprintContext === null || fingerprintContext === void 0 ? void 0 : fingerprintContext.xUser) === null || _a === void 0 ? void 0 : _a.clerkUserId),
43
+ subscriptionStatus: getUserState(),
44
+ subscriptionType: ((_c = (_b = fingerprintContext === null || fingerprintContext === void 0 ? void 0 : fingerprintContext.xSubscription) === null || _b === void 0 ? void 0 : _b.priceId) === null || _c === void 0 ? void 0 : _c.includes('yearly')) ? 'yearly' : 'monthly',
45
+ subscriptionEndDate: (_d = fingerprintContext === null || fingerprintContext === void 0 ? void 0 : fingerprintContext.xSubscription) === null || _d === void 0 ? void 0 : _d.subPeriodEnd
46
+ });
47
+ }, [fingerprintContext, getUserState]);
46
48
  // 处理登录
47
- const handleLogin = () => {
49
+ const handleLogin = React.useCallback(() => {
48
50
  if (signInPath) {
49
51
  router.push(signInPath);
50
52
  }
51
53
  else {
52
54
  redirectToSignIn();
53
55
  }
54
- };
56
+ }, [signInPath, redirectToSignIn, router]);
55
57
  // 处理升级
56
- const handleUpgrade = (plan, billingType) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
57
- // 如果没有配置 API 端点,跳转到首页
58
+ const handleUpgrade = React.useCallback((plan, billingType) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
58
59
  if (!upgradeApiEndpoint) {
59
60
  router.push('/');
60
61
  return;
61
62
  }
62
63
  setIsProcessing(true);
63
64
  try {
64
- // 获取价格配置
65
- const pricing = moneyPriceConfig.getProductPricing(plan, billingType, config.activeProvider, config);
66
- // 调用 API 创建支付会话
65
+ const pricing = moneyPriceConfigUtil.getProductPricing(plan, billingType, config.activeProvider, config);
67
66
  const response = yield fetch(upgradeApiEndpoint, {
68
67
  method: 'POST',
69
68
  headers: {
@@ -78,7 +77,6 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
78
77
  });
79
78
  const result = yield response.json();
80
79
  if (result.success && result.checkoutUrl) {
81
- // 跳转到支付页面
82
80
  window.location.href = result.checkoutUrl;
83
81
  }
84
82
  else {
@@ -91,14 +89,13 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
91
89
  finally {
92
90
  setIsProcessing(false);
93
91
  }
94
- });
92
+ }), [upgradeApiEndpoint, config, router]);
95
93
  // 更新价格显示
96
- const updatePriceDisplay = (newBillingType) => {
97
- const providerConfig = moneyPriceConfig.getActiveProviderConfig(config);
94
+ const updatePriceDisplay = React.useCallback((newBillingType) => {
95
+ const providerConfig = moneyPriceConfigUtil.getActiveProviderConfig(config);
98
96
  data.plans.forEach((plan) => {
99
97
  const productConfig = providerConfig.products[plan.key];
100
98
  const pricing = productConfig.plans[newBillingType];
101
- // 更新价格值
102
99
  const priceValueElement = document.querySelector(`[data-price-value="${plan.key}"]`);
103
100
  if (priceValueElement) {
104
101
  if (pricing.amount === 0) {
@@ -108,13 +105,11 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
108
105
  priceValueElement.textContent = `${data.currency}${pricing.amount}`;
109
106
  }
110
107
  }
111
- // 更新单位
112
108
  const priceUnitElement = document.querySelector(`[data-price-unit="${plan.key}"]`);
113
109
  if (priceUnitElement) {
114
110
  const billingOption = data.billingSwitch.options.find(opt => opt.key === newBillingType);
115
111
  priceUnitElement.textContent = (billingOption === null || billingOption === void 0 ? void 0 : billingOption.unit) || '/month';
116
112
  }
117
- // 更新原价和折扣
118
113
  const priceOriginalElement = document.querySelector(`[data-price-original="${plan.key}"]`);
119
114
  const priceDiscountElement = document.querySelector(`[data-price-discount="${plan.key}"]`);
120
115
  if (pricing.originalAmount && pricing.discountPercent) {
@@ -136,16 +131,15 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
136
131
  if (priceDiscountElement)
137
132
  priceDiscountElement.style.display = 'none';
138
133
  }
139
- // 更新副标题
140
134
  const priceSubtitleElement = document.querySelector(`[data-price-subtitle="${plan.key}"]`);
141
135
  if (priceSubtitleElement && plan.showBillingSubTitle !== false) {
142
136
  const billingOption = data.billingSwitch.options.find(opt => opt.key === newBillingType);
143
137
  priceSubtitleElement.textContent = (billingOption === null || billingOption === void 0 ? void 0 : billingOption.subTitle) || '';
144
138
  }
145
139
  });
146
- };
140
+ }, [config, data]);
147
141
  // 更新按钮样式
148
- const updateButtonStyles = (newBillingType) => {
142
+ const updateButtonStyles = React.useCallback((newBillingType) => {
149
143
  const monthlyButton = document.querySelector('[data-billing-button="monthly"]');
150
144
  const yearlyButton = document.querySelector('[data-billing-button="yearly"]');
151
145
  const activeClasses = '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';
@@ -160,15 +154,14 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
160
154
  yearlyButton.className = utils.cn('min-w-[120px] px-6 py-2 font-medium transition text-lg relative', activeClasses);
161
155
  }
162
156
  }
163
- };
157
+ }, []);
164
158
  // 更新折扣信息
165
- const updateDiscountInfo = (newBillingType) => {
159
+ const updateDiscountInfo = React.useCallback((newBillingType) => {
166
160
  const discountInfoElement = document.querySelector('[data-discount-info]');
167
161
  if (!discountInfoElement)
168
162
  return;
169
163
  const billingOption = data.billingSwitch.options.find(opt => opt.key === newBillingType);
170
- const providerConfig = moneyPriceConfig.getActiveProviderConfig(config);
171
- // 检查是否有折扣
164
+ const providerConfig = moneyPriceConfigUtil.getActiveProviderConfig(config);
172
165
  let hasDiscount = false;
173
166
  let discountPercent = 0;
174
167
  ['pro', 'ultra'].forEach(planKey => {
@@ -179,7 +172,6 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
179
172
  discountPercent = pricing.discountPercent;
180
173
  }
181
174
  });
182
- // 清空内容
183
175
  discountInfoElement.innerHTML = '';
184
176
  if (hasDiscount && (billingOption === null || billingOption === void 0 ? void 0 : billingOption.discountText)) {
185
177
  const discountBadge = document.createElement('span');
@@ -187,17 +179,7 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
187
179
  discountBadge.textContent = billingOption.discountText.replace('{percent}', String(discountPercent));
188
180
  discountInfoElement.appendChild(discountBadge);
189
181
  }
190
- };
191
- // 动态替换按钮
192
- React.useEffect(() => {
193
- data.plans.forEach((plan) => {
194
- const placeholder = document.querySelector(`[data-button-placeholder="${plan.key}"]`);
195
- if (placeholder) {
196
- const root = client.createRoot(placeholder);
197
- root.render(jsxRuntime.jsx(moneyPriceButton.MoneyPriceButton, { planKey: plan.key, userContext: userContext, billingType: billingType, onLogin: handleLogin, onUpgrade: handleUpgrade, texts: data.buttonTexts, isProcessing: isProcessing }));
198
- }
199
- });
200
- }, [userContext, billingType, isProcessing]);
182
+ }, [config, data]);
201
183
  // 处理月付/年付切换和 tooltip 功能
202
184
  React.useEffect(() => {
203
185
  const monthlyButton = document.querySelector('[data-billing-button="monthly"]');
@@ -220,7 +202,6 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
220
202
  if (yearlyButton) {
221
203
  yearlyButton.addEventListener('click', handleYearlyClick);
222
204
  }
223
- // 添加 tooltip 功能
224
205
  const tooltipHandlers = [];
225
206
  data.plans.forEach((plan) => {
226
207
  var _a;
@@ -252,10 +233,8 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
252
233
  }
253
234
  });
254
235
  });
255
- // 初始化价格显示
256
236
  updatePriceDisplay(billingType);
257
237
  updateDiscountInfo(billingType);
258
- // 清理
259
238
  return () => {
260
239
  if (monthlyButton) {
261
240
  monthlyButton.removeEventListener('click', handleMonthlyClick);
@@ -263,14 +242,13 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
263
242
  if (yearlyButton) {
264
243
  yearlyButton.removeEventListener('click', handleYearlyClick);
265
244
  }
266
- // 清理 tooltip 事件监听器
267
245
  tooltipHandlers.forEach(({ element, handlers }) => {
268
246
  element.removeEventListener('mouseenter', handlers.mouseenter);
269
247
  element.removeEventListener('mousemove', handlers.mousemove);
270
248
  element.removeEventListener('mouseleave', handlers.mouseleave);
271
249
  });
272
250
  };
273
- }, [data]);
251
+ }, [data, billingType, updatePriceDisplay, updateButtonStyles, updateDiscountInfo]);
274
252
  // Tooltip 组件
275
253
  const Tooltip = ({ show, content, x, y }) => {
276
254
  if (!show)
@@ -287,7 +265,8 @@ function MoneyPriceInteractive({ data, config, upgradeApiEndpoint, signInPath })
287
265
  };
288
266
  return (jsxRuntime.jsx("div", { style: style, className: "bg-gray-700 dark:bg-gray-200 text-gray-100 dark:text-gray-800 text-xs leading-relaxed px-3 py-2 rounded-lg shadow-lg border border-gray-300 dark:border-gray-600 backdrop-blur-sm", children: content }));
289
267
  };
290
- return jsxRuntime.jsx(Tooltip, Object.assign({}, tooltip));
268
+ // 直接渲染按钮,确保宽度占满
269
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [data.plans.map((plan) => (jsxRuntime.jsx("div", { "data-button-placeholder": plan.key, children: jsxRuntime.jsx(moneyPriceButton.MoneyPriceButton, { planKey: plan.key, userContext: userContext, billingType: billingType, onLogin: handleLogin, onUpgrade: handleUpgrade, texts: data.buttonTexts, isProcessing: isProcessing }) }, plan.key))), jsxRuntime.jsx(Tooltip, Object.assign({}, tooltip))] }));
291
270
  }
292
271
 
293
272
  exports.MoneyPriceInteractive = MoneyPriceInteractive;