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/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>Vite + Preact + TS</title>
7
+ <title>组件库 Demo</title>
8
8
  </head>
9
9
  <body>
10
10
  <div id="app"></div>
11
- <script type="module" src="/src/main.tsx"></script>
11
+ <script type="module" src="/src/demo/index.tsx"></script>
12
12
  </body>
13
13
  </html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "best-unit",
3
3
  "private": false,
4
- "version": "0.0.7",
4
+ "version": "0.0.8",
5
5
  "type": "module",
6
6
  "main": "dist/best-unit.cjs",
7
7
  "module": "dist/best-unit.js",
@@ -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: { name: string; email: string }) => Promise<void>;
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 [name, setName] = useState('');
12
- const [email, setEmail] = useState('');
13
- const [loading, setLoading] = useState(false);
14
- const [error, setError] = useState('');
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
- setLoading(true);
21
- setError('');
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({ name, email });
55
+ await onSubmit({ amount: formState.amount, rechargeChannel: formState.rechargeChannel, currency: formState.currency });
24
56
  onClose();
25
57
  } catch {
26
- setError('提交失败,请重试');
58
+ setFormState(state => ({ ...state, error: '提交失败,请重试' }));
27
59
  } finally {
28
- setLoading(false);
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 style={{
34
- position: 'fixed', top: 0, left: 0, right: 0, bottom: 0,
35
- background: 'rgba(0,0,0,0.3)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9999
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: '#fff', padding: 24, borderRadius: 8, minWidth: 320 }}
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
- <h2 style={{ color: color || '#1890ff' }}>表单</h2>
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={{ marginLeft: 12, background: '#eee', color: '#333', border: 'none', borderRadius: 4, padding: '8px 16px', cursor: 'pointer', fontSize: 16 }}
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: { name: string; email: string }) => {
10
+ const handleSubmit = async (form: { amount: string; rechargeChannel: string; currency: string }) => {
11
11
  console.log('submit', form);
12
12
  };
13
13
 
@@ -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
+ }
@@ -0,0 +1,4 @@
1
+ import { render } from 'preact';
2
+ import DemoApp from './App.tsx';
3
+
4
+ render(<DemoApp />, document.getElementById('app')!);
package/src/main.ts CHANGED
@@ -1,6 +1,5 @@
1
1
 
2
2
  import { npmTest, printCurrentTime } from './index.ts'
3
- import './app.tsx'
4
3
  import './components/ModalForm'
5
4
 
6
5
  // 可选:导出组件列表或版本信息
@@ -9,3 +8,7 @@ export {
9
8
  npmTest,
10
9
  printCurrentTime,
11
10
  }
11
+
12
+
13
+
14
+
package/src/app.tsx DELETED
@@ -1,9 +0,0 @@
1
- import register from 'preact-custom-element';
2
-
3
- const Greeting = ({ name = 'World' }) => (
4
- <p>Hello, {name}!</p>
5
- );
6
-
7
- register(Greeting, 'x-greeting', ['name'], { shadow: false });
8
-
9
- export default Greeting;