best-unit 0.0.7 → 0.0.8
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/best-unit.cjs +1 -1
- package/dist/best-unit.js +577 -447
- package/index.html +2 -2
- package/package.json +1 -1
- package/src/components/ModalForm/components/ModalForm.tsx +156 -47
- package/src/components/ModalForm/index.tsx +1 -1
- package/src/demo/App.tsx +19 -0
- package/src/demo/index.tsx +4 -0
- package/src/main.ts +4 -1
- package/src/app.tsx +0 -9
package/index.html
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title
|
|
7
|
+
<title>组件库 Demo</title>
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<div id="app"></div>
|
|
11
|
-
<script type="module" src="/src/
|
|
11
|
+
<script type="module" src="/src/demo/index.tsx"></script>
|
|
12
12
|
</body>
|
|
13
13
|
</html>
|
package/package.json
CHANGED
|
@@ -1,79 +1,188 @@
|
|
|
1
|
-
import { useState } from 'preact/hooks';
|
|
1
|
+
import { useState, useEffect } from 'preact/hooks';
|
|
2
2
|
|
|
3
3
|
interface ModalFormProps {
|
|
4
4
|
visible: boolean;
|
|
5
5
|
onClose: () => void;
|
|
6
|
-
onSubmit: (form: {
|
|
6
|
+
onSubmit: (form: { amount: string; rechargeChannel: string; currency: string }) => Promise<void>;
|
|
7
7
|
color?: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export function ModalForm({ visible, onClose, onSubmit, color }: ModalFormProps) {
|
|
11
|
-
const [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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]);
|
|
15
37
|
|
|
16
38
|
if (!visible) return null;
|
|
17
39
|
|
|
18
40
|
const handleSubmit = async (e: Event) => {
|
|
19
41
|
e.preventDefault();
|
|
20
|
-
|
|
21
|
-
|
|
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: '' }));
|
|
22
54
|
try {
|
|
23
|
-
await onSubmit({
|
|
55
|
+
await onSubmit({ amount: formState.amount, rechargeChannel: formState.rechargeChannel, currency: formState.currency });
|
|
24
56
|
onClose();
|
|
25
57
|
} catch {
|
|
26
|
-
|
|
58
|
+
setFormState(state => ({ ...state, error: '提交失败,请重试' }));
|
|
27
59
|
} finally {
|
|
28
|
-
|
|
60
|
+
setFormState(state => ({ ...state, loading: false }));
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// 点击弹窗外部关闭
|
|
65
|
+
const handleMaskClick = (e: any) => {
|
|
66
|
+
if (e.target === e.currentTarget) {
|
|
67
|
+
onClose();
|
|
29
68
|
}
|
|
30
69
|
};
|
|
31
70
|
|
|
32
71
|
return (
|
|
33
|
-
<div
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
+
>
|
|
37
79
|
<form
|
|
38
80
|
onSubmit={handleSubmit}
|
|
39
|
-
style={{ background: '#
|
|
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()}
|
|
40
85
|
>
|
|
41
|
-
|
|
42
|
-
<div style={{ marginBottom: 12 }}>
|
|
43
|
-
<input
|
|
44
|
-
type="text"
|
|
45
|
-
placeholder="姓名"
|
|
46
|
-
value={name}
|
|
47
|
-
onInput={e => setName((e.target as HTMLInputElement).value)}
|
|
48
|
-
required
|
|
49
|
-
style={{ width: '100%', padding: 8, marginBottom: 8 }}
|
|
50
|
-
/>
|
|
51
|
-
<input
|
|
52
|
-
type="email"
|
|
53
|
-
placeholder="邮箱"
|
|
54
|
-
value={email}
|
|
55
|
-
onInput={e => setEmail((e.target as HTMLInputElement).value)}
|
|
56
|
-
required
|
|
57
|
-
style={{ width: '100%', padding: 8 }}
|
|
58
|
-
/>
|
|
59
|
-
</div>
|
|
60
|
-
{error && <div style={{ color: 'red', marginBottom: 8 }}>{error}</div>}
|
|
61
|
-
<button
|
|
62
|
-
type="submit"
|
|
63
|
-
disabled={loading}
|
|
64
|
-
style={{
|
|
65
|
-
background: color || '#1890ff', color: '#fff', border: 'none', borderRadius: 4, padding: '8px 16px', cursor: 'pointer', fontSize: 16
|
|
66
|
-
}}
|
|
67
|
-
>
|
|
68
|
-
{loading ? '提交中...' : '提交'}
|
|
69
|
-
</button>
|
|
86
|
+
{/* 关闭按钮 */}
|
|
70
87
|
<button
|
|
71
88
|
type="button"
|
|
72
89
|
onClick={onClose}
|
|
73
|
-
style={{
|
|
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="关闭"
|
|
74
94
|
>
|
|
75
|
-
|
|
95
|
+
×
|
|
76
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>
|
|
77
186
|
</form>
|
|
78
187
|
</div>
|
|
79
188
|
);
|
|
@@ -7,7 +7,7 @@ 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: {
|
|
10
|
+
const handleSubmit = async (form: { amount: string; rechargeChannel: string; currency: string }) => {
|
|
11
11
|
console.log('submit', form);
|
|
12
12
|
};
|
|
13
13
|
|
package/src/demo/App.tsx
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { npmTest, printCurrentTime } from '../main';
|
|
2
|
+
import { BestUnit } from '../components/ModalForm';
|
|
3
|
+
|
|
4
|
+
export default function DemoApp() {
|
|
5
|
+
return (
|
|
6
|
+
<div>
|
|
7
|
+
<h2>组件库可视化测试</h2>
|
|
8
|
+
<div>
|
|
9
|
+
<h3>BestUnit 组件演示:</h3>
|
|
10
|
+
<BestUnit theme={{ primaryColor: '#6366f1' }} />
|
|
11
|
+
</div>
|
|
12
|
+
<div>
|
|
13
|
+
<h3>方法演示:</h3>
|
|
14
|
+
<button onClick={npmTest} style={{ marginRight: 10 }}>调用 npmTest()</button>
|
|
15
|
+
<button onClick={printCurrentTime}>调用 printCurrentTime()</button>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
}
|
package/src/main.ts
CHANGED