@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.
- 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 +0 -2
- package/dist/main/faq.mjs +0 -2
- package/dist/main/gallery.js +0 -2
- package/dist/main/gallery.mjs +0 -2
- 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-interactive.js +29 -50
- package/dist/main/money-price/money-price-interactive.mjs +28 -49
- package/dist/main/money-price/money-price-types.d.ts +1 -1
- package/dist/main/money-price/money-price.js +3 -23
- package/dist/main/money-price/money-price.mjs +2 -22
- package/dist/main/price-plan.js +0 -2
- package/dist/main/price-plan.mjs +0 -2
- package/dist/main/server.d.ts +1 -1
- package/dist/main/server.js +3 -4
- package/dist/main/server.mjs +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/money-price/money-price-config-util.ts +23 -0
- package/src/main/money-price/money-price-interactive.tsx +47 -64
- package/src/main/money-price/money-price-types.ts +1 -1
- package/src/main/money-price/money-price.tsx +5 -32
- package/src/main/server.ts +1 -2
- 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(
|
|
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
|
-
}
|
|
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: '
|
|
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
|
|
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(
|
|
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
|
-
}
|
|
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: '
|
|
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
|
|
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 };
|
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 }) {
|
package/dist/main/gallery.js
CHANGED
|
@@ -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 }) {
|
package/dist/main/gallery.mjs
CHANGED
|
@@ -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
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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;
|