best-unit 0.0.8 → 0.0.9

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.
@@ -0,0 +1,244 @@
1
+ import { useState, useEffect } from "preact/hooks";
2
+ import { OnlineRechargeForm } from "./OnlineRechargeForm";
3
+ import { OfflineTransferForm } from "./OfflineTransferForm";
4
+
5
+ interface ModalFormProps {
6
+ visible: boolean;
7
+ onClose: () => void;
8
+ onSubmit: (form: {
9
+ amount: string;
10
+ rechargeChannel: string;
11
+ currency: string;
12
+ }) => Promise<void>;
13
+ color?: string;
14
+ }
15
+
16
+ export function ModalForm({
17
+ visible,
18
+ onClose,
19
+ onSubmit,
20
+ color,
21
+ }: ModalFormProps) {
22
+ console.log(1111);
23
+ const [formState, setFormState] = useState({
24
+ amount: "",
25
+ rechargeChannel: "paypal",
26
+ currency: "USD",
27
+ loading: false,
28
+ error: "",
29
+ amountError: "",
30
+ rechargeChannelError: "",
31
+ currencyError: "",
32
+ });
33
+ const [activeTab, setActiveTab] = useState<"online" | "offline">("online");
34
+ const [offlineFormState, setOfflineFormState] = useState({
35
+ platform: "paypal",
36
+ transactionId: "",
37
+ files: [],
38
+ platformError: "",
39
+ transactionIdError: "",
40
+ filesError: "",
41
+ loading: false,
42
+ });
43
+
44
+ // 每次关闭弹窗时重置内容
45
+ useEffect(() => {
46
+ if (!visible) {
47
+ setActiveTab("online");
48
+ setFormState({
49
+ amount: "",
50
+ rechargeChannel: "paypal",
51
+ currency: "USD",
52
+ loading: false,
53
+ error: "",
54
+ amountError: "",
55
+ rechargeChannelError: "",
56
+ currencyError: "",
57
+ });
58
+ setOfflineFormState({
59
+ platform: "paypal",
60
+ transactionId: "",
61
+ files: [],
62
+ platformError: "",
63
+ transactionIdError: "",
64
+ filesError: "",
65
+ loading: false,
66
+ });
67
+ }
68
+ }, [visible]);
69
+
70
+ if (!visible) return null;
71
+
72
+ const handleSubmit = async (e: Event) => {
73
+ e.preventDefault();
74
+ let valid = true;
75
+ setFormState((state) => ({
76
+ ...state,
77
+ amountError: "",
78
+ rechargeChannelError: "",
79
+ }));
80
+ if (!formState.amount.trim()) {
81
+ setFormState((state) => ({ ...state, amountError: "请输入充值金额" }));
82
+ valid = false;
83
+ }
84
+ if (!formState.rechargeChannel) {
85
+ setFormState((state) => ({
86
+ ...state,
87
+ rechargeChannelError: "请选择支付平台",
88
+ }));
89
+ valid = false;
90
+ }
91
+ if (!valid) return;
92
+ setFormState((state) => ({ ...state, loading: true, error: "" }));
93
+ try {
94
+ await onSubmit({
95
+ amount: formState.amount,
96
+ rechargeChannel: formState.rechargeChannel,
97
+ currency: formState.currency,
98
+ });
99
+ onClose();
100
+ } catch {
101
+ setFormState((state) => ({ ...state, error: "提交失败,请重试" }));
102
+ } finally {
103
+ setFormState((state) => ({ ...state, loading: false }));
104
+ }
105
+ };
106
+
107
+ // 点击弹窗外部关闭
108
+ const handleMaskClick = (e: any) => {
109
+ if (e.target === e.currentTarget) {
110
+ onClose();
111
+ }
112
+ };
113
+
114
+ return (
115
+ <div
116
+ style={{
117
+ position: "fixed",
118
+ top: 0,
119
+ left: 0,
120
+ right: 0,
121
+ bottom: 0,
122
+ background: "rgba(0,0,0,0.3)", // 更浅的遮罩
123
+ display: "flex",
124
+ alignItems: "center",
125
+ justifyContent: "center",
126
+ zIndex: 9999,
127
+ }}
128
+ onClick={handleMaskClick}
129
+ >
130
+ <form
131
+ onSubmit={handleSubmit}
132
+ style={{
133
+ background: "#fff", // 白色弹窗
134
+ padding: 32,
135
+ borderRadius: 12,
136
+ minWidth: 400,
137
+ color: color || "#222", // 深色字体
138
+ boxShadow: "0 4px 24px rgba(0,0,0,0.08)",
139
+ position: "relative",
140
+ }}
141
+ onClick={(e) => e.stopPropagation()}
142
+ >
143
+ {/* 关闭按钮 */}
144
+ <button
145
+ type="button"
146
+ onClick={onClose}
147
+ style={{
148
+ position: "absolute",
149
+ right: 16,
150
+ top: 16,
151
+ background: "none",
152
+ border: "none",
153
+ color: "#222",
154
+ fontSize: 22,
155
+ cursor: "pointer",
156
+ lineHeight: 1,
157
+ }}
158
+ aria-label="关闭"
159
+ >
160
+ ×
161
+ </button>
162
+ <div
163
+ style={{
164
+ fontWeight: 600,
165
+ fontSize: 20,
166
+ marginBottom: 24,
167
+ textAlign: "left",
168
+ color: "#222",
169
+ }}
170
+ >
171
+ 充值 / 转账
172
+ </div>
173
+ {/* tab 按钮区域 */}
174
+ <div style={{ display: "flex", marginBottom: 28 }}>
175
+ <button
176
+ type="button"
177
+ onClick={() => setActiveTab("online")}
178
+ style={{
179
+ flex: 1,
180
+ background: activeTab === "online" ? "#fff" : "#F7F8FA",
181
+ color: activeTab === "online" ? "#155EEF" : "#222",
182
+ border: "none",
183
+ borderRadius: "8px 0 0 8px",
184
+ fontWeight: activeTab === "online" ? 600 : 400,
185
+ fontSize: 16,
186
+ height: 48,
187
+ boxShadow:
188
+ activeTab === "online"
189
+ ? "0 2px 8px 0 rgba(20,20,20,0.04)"
190
+ : "none",
191
+ outline: "none",
192
+ cursor: "pointer",
193
+ borderRight: "1px solid #F0F1F3",
194
+ transition: "all 0.2s",
195
+ }}
196
+ >
197
+ 在线充值
198
+ </button>
199
+ <button
200
+ type="button"
201
+ onClick={() => setActiveTab("offline")}
202
+ style={{
203
+ flex: 1,
204
+ background: activeTab === "offline" ? "#fff" : "#F7F8FA",
205
+ color: activeTab === "offline" ? "#155EEF" : "#222",
206
+ border: "none",
207
+ borderRadius: "0 8px 8px 0",
208
+ fontWeight: activeTab === "offline" ? 600 : 400,
209
+ fontSize: 16,
210
+ height: 48,
211
+ boxShadow:
212
+ activeTab === "offline"
213
+ ? "0 2px 8px 0 rgba(20,20,20,0.04)"
214
+ : "none",
215
+ outline: "none",
216
+ cursor: "pointer",
217
+ borderLeft: "1px solid #F0F1F3",
218
+ transition: "all 0.2s",
219
+ }}
220
+ >
221
+ 线下转账
222
+ </button>
223
+ </div>
224
+ {/* tab 内容区域 */}
225
+ {activeTab === "online" ? (
226
+ <OnlineRechargeForm
227
+ formState={formState}
228
+ setFormState={setFormState}
229
+ onClose={onClose}
230
+ loading={formState.loading}
231
+ whiteTheme={true}
232
+ />
233
+ ) : (
234
+ <OfflineTransferForm
235
+ formState={offlineFormState}
236
+ setFormState={setOfflineFormState}
237
+ onClose={onClose}
238
+ loading={offlineFormState.loading}
239
+ />
240
+ )}
241
+ </form>
242
+ </div>
243
+ );
244
+ }
@@ -1,14 +1,18 @@
1
- import { useState } from 'preact/hooks';
2
- import { ThemedButton } from './components/Button';
3
- import { ModalForm } from './components/ModalForm';
4
- import register from 'preact-custom-element';
1
+ import { useState } from "preact/hooks";
2
+ import { ThemedButton } from "./components/Button";
3
+ import { ModalForm } from "./components/recharge";
4
+ import register from "preact-custom-element";
5
5
 
6
6
  export function BestUnit(props: any) {
7
7
  const [visible, setVisible] = useState(false);
8
8
  const color = props.theme?.primaryColor;
9
9
 
10
- const handleSubmit = async (form: { amount: string; rechargeChannel: string; currency: string }) => {
11
- console.log('submit', form);
10
+ const handleSubmit = async (form: {
11
+ amount: string;
12
+ rechargeChannel: string;
13
+ currency: string;
14
+ }) => {
15
+ console.log("submit", form);
12
16
  };
13
17
 
14
18
  return (
@@ -26,7 +30,6 @@ export function BestUnit(props: any) {
26
30
  );
27
31
  }
28
32
 
29
-
30
- register(BestUnit, 'x-best-modal-form', ['theme'], { shadow: false });
33
+ register(BestUnit, "x-best-modal-form", ["theme"], { shadow: false });
31
34
 
32
35
  export default BestUnit;
package/tsconfig.json CHANGED
@@ -8,5 +8,8 @@
8
8
  "references": [
9
9
  { "path": "./tsconfig.app.json" },
10
10
  { "path": "./tsconfig.node.json" }
11
- ]
11
+ ],
12
+ "editor.codeActionsOnSave": {
13
+ "source.fixAll.eslint": true
14
+ }
12
15
  }
@@ -1,189 +0,0 @@
1
- import { useState, useEffect } from 'preact/hooks';
2
-
3
- interface ModalFormProps {
4
- visible: boolean;
5
- onClose: () => void;
6
- onSubmit: (form: { amount: string; rechargeChannel: string; currency: string }) => Promise<void>;
7
- color?: string;
8
- }
9
-
10
- export function ModalForm({ visible, onClose, onSubmit, color }: ModalFormProps) {
11
- const [formState, setFormState] = useState({
12
- amount: '',
13
- rechargeChannel: 'paypal',
14
- currency: 'USD',
15
- loading: false,
16
- error: '',
17
- amountError: '',
18
- rechargeChannelError: '',
19
- currencyError: ''
20
- });
21
-
22
- // 每次关闭弹窗时重置内容
23
- useEffect(() => {
24
- if (!visible) {
25
- setFormState({
26
- amount: '',
27
- rechargeChannel: 'paypal',
28
- currency: 'USD',
29
- loading: false,
30
- error: '',
31
- amountError: '',
32
- rechargeChannelError: '',
33
- currencyError: ''
34
- });
35
- }
36
- }, [visible]);
37
-
38
- if (!visible) return null;
39
-
40
- const handleSubmit = async (e: Event) => {
41
- e.preventDefault();
42
- let valid = true;
43
- setFormState(state => ({ ...state, amountError: '', rechargeChannelError: '' }));
44
- if (!formState.amount.trim()) {
45
- setFormState(state => ({ ...state, amountError: '请输入充值金额' }));
46
- valid = false;
47
- }
48
- if (!formState.rechargeChannel) {
49
- setFormState(state => ({ ...state, rechargeChannelError: '请选择支付平台' }));
50
- valid = false;
51
- }
52
- if (!valid) return;
53
- setFormState(state => ({ ...state, loading: true, error: '' }));
54
- try {
55
- await onSubmit({ amount: formState.amount, rechargeChannel: formState.rechargeChannel, currency: formState.currency });
56
- onClose();
57
- } catch {
58
- setFormState(state => ({ ...state, error: '提交失败,请重试' }));
59
- } finally {
60
- setFormState(state => ({ ...state, loading: false }));
61
- }
62
- };
63
-
64
- // 点击弹窗外部关闭
65
- const handleMaskClick = (e: any) => {
66
- if (e.target === e.currentTarget) {
67
- onClose();
68
- }
69
- };
70
-
71
- return (
72
- <div
73
- style={{
74
- position: 'fixed', top: 0, left: 0, right: 0, bottom: 0,
75
- background: 'rgba(0,0,0,0.7)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9999
76
- }}
77
- onClick={handleMaskClick}
78
- >
79
- <form
80
- onSubmit={handleSubmit}
81
- style={{ background: '#181A20', padding: 32, borderRadius: 12, minWidth: 360,
82
- color: color || '#fff', boxShadow: '0 4px 24px rgba(0,0,0,0.5)',
83
- position: 'relative' }}
84
- onClick={e => e.stopPropagation()}
85
- >
86
- {/* 关闭按钮 */}
87
- <button
88
- type="button"
89
- onClick={onClose}
90
- style={{
91
- position: 'absolute', right: 16, top: 16, background: 'none', border: 'none', color: '#fff', fontSize: 22, cursor: 'pointer', lineHeight: 1
92
- }}
93
- aria-label="关闭"
94
- >
95
- ×
96
- </button>
97
- <div style={{ fontWeight: 600, fontSize: 18, marginBottom: 24, textAlign: 'left' }}>在线充值</div>
98
- <div style={{ marginBottom: 18 }}>
99
- <div style={{ marginBottom: 8, fontSize: 14 }}><span style={{ color: '#00E8C6' }}>*</span> 充值金额</div>
100
- <input
101
- type="text"
102
- placeholder="请输入充值金额"
103
- value={formState.amount}
104
- onInput={e => {
105
- const value = (e.target as HTMLInputElement).value;
106
- setFormState(state => ({
107
- ...state,
108
- amount: value,
109
- amountError: value.trim() ? '' : state.amountError
110
- }));
111
- }}
112
- style={{
113
- width: '100%',
114
- padding: '10px 12px',
115
- borderRadius: 6,
116
- boxSizing: 'border-box',
117
- border: formState.amountError ? '1px solid #ff4d4f' : '1px solid #23262F',
118
- background: '#23262F',
119
- color: '#fff',
120
- fontSize: 15,
121
- outline: 'none',
122
- marginBottom: 0
123
- }}
124
- />
125
- {formState.amountError && <div style={{ color: '#ff4d4f', fontSize: 13, marginTop: 4 }}>{formState.amountError}</div>}
126
- </div>
127
- <div style={{ marginBottom: 18 }}>
128
- <div style={{ marginBottom: 8, fontSize: 14 }}><span style={{ color: '#00E8C6' }}>*</span> 支付平台</div>
129
- <select
130
- style={{
131
- width: '100%',
132
- padding: '10px 12px',
133
- borderRadius: 6,
134
- border: formState.rechargeChannelError ? '1px solid #ff4d4f' : '1px solid #23262F',
135
- background: '#23262F',
136
- color: '#fff',
137
- fontSize: 15,
138
- outline: 'none'
139
- }}
140
- value={formState.rechargeChannel}
141
- onInput={e => {
142
- const value = (e.target as HTMLSelectElement).value;
143
- setFormState(state => ({
144
- ...state,
145
- rechargeChannel: value,
146
- rechargeChannelError: value ? '' : state.rechargeChannelError
147
- }));
148
- }}
149
- >
150
- <option value="alipay">支付宝</option>
151
- <option value="wechat">微信</option>
152
- <option value="paypal">PayPal</option>
153
- </select>
154
- {formState.rechargeChannelError && <div style={{ color: '#ff4d4f', fontSize: 13, marginTop: 4 }}>{formState.rechargeChannelError}</div>}
155
- </div>
156
- <div style={{ marginBottom: 24 }}>
157
- <div style={{ marginBottom: 8, fontSize: 14 }}>币种</div>
158
- <select
159
- style={{ width: '100%', padding: '10px 12px', borderRadius: 6,
160
- border: '1px solid #23262F', background: '#23262F',
161
- color: '#fff', fontSize: 15, outline: 'none' }}
162
- value={formState.currency}
163
- >
164
- <option value="USD">USD</option>
165
- <option value="CNY">CNY</option>
166
- <option value="EUR">EUR</option>
167
- </select>
168
- </div>
169
- {formState.error && <div style={{ color: '#ff4d4f', marginBottom: 12 }}>{formState.error}</div>}
170
- <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12 }}>
171
- <button
172
- type="button"
173
- onClick={onClose}
174
- style={{ background: '#23262F', color: '#fff', border: 'none', borderRadius: 6, padding: '8px 24px', fontSize: 15, cursor: 'pointer' }}
175
- >
176
- 取消
177
- </button>
178
- <button
179
- type="submit"
180
- disabled={formState.loading}
181
- style={{ background: '#00E8C6', color: '#fff', border: 'none', borderRadius: 6, padding: '8px 24px', fontSize: 15, cursor: 'pointer', fontWeight: 600 }}
182
- >
183
- {formState.loading ? '提交中...' : '去支付'}
184
- </button>
185
- </div>
186
- </form>
187
- </div>
188
- );
189
- }