react-unified-auth 1.0.1 → 1.0.3

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/README.md CHANGED
@@ -1,19 +1,19 @@
1
- # React Unified Auth
2
-
3
- 一个用于三方登录的统一入口React组件库,支持动态表单和可配置的认证流程。
4
-
5
- ## 功能特性
6
-
7
- - 动态表单渲染:通过HTTP请求获取表单结构并动态渲染
8
- - 可配置的认证流程:支持自定义API端点和参数
9
- - 预构建的UI组件:登录表单、用户信息框、社交登录按钮等
10
- - TypeScript支持:完整的类型定义
11
- - React Hooks:提供便捷的认证和表单管理hooks
12
-
13
- ## 安装
14
-
15
- ```bash
16
- npm install react-unified-auth
1
+ # React Unified Auth
2
+
3
+ 一个用于三方登录的统一入口React组件库,支持动态表单和可配置的认证流程。
4
+
5
+ ## 功能特性
6
+
7
+ - 动态表单渲染:通过HTTP请求获取表单结构并动态渲染
8
+ - 可配置的认证流程:支持自定义API端点和参数
9
+ - 预构建的UI组件:登录表单、用户信息框、社交登录按钮等
10
+ - TypeScript支持:完整的类型定义
11
+ - React Hooks:提供便捷的认证和表单管理hooks
12
+
13
+ ## 安装
14
+
15
+ ```bash
16
+ npm install react-unified-auth
17
17
  ```
18
18
 
19
19
  ## 使用方法
@@ -23,7 +23,8 @@ npm install react-unified-auth
23
23
  在你的应用根组件中包裹`AuthProvider`:
24
24
 
25
25
  ```tsx
26
- import { AuthProvider } from 'react-social-auth';
26
+ import { AuthProvider } from 'react-unified-auth';
27
+ import 'react-unified-auth/dist/index.css';
27
28
 
28
29
  function App() {
29
30
  const config = {
@@ -47,7 +48,7 @@ function App() {
47
48
  ### 2. 使用登录表单
48
49
 
49
50
  ```tsx
50
- import { LoginForm } from 'react-social-auth';
51
+ import { LoginForm } from 'react-unified-auth';
51
52
 
52
53
  function LoginPage() {
53
54
  return (
@@ -65,7 +66,7 @@ function LoginPage() {
65
66
  ### 3. 使用用户信息框
66
67
 
67
68
  ```tsx
68
- import { UserInfoBox, useAuth } from 'react-social-auth';
69
+ import { UserInfoBox, useAuth } from 'react-unified-auth';
69
70
 
70
71
  function UserProfile() {
71
72
  const { user, logout } = useAuth();
@@ -84,7 +85,7 @@ function UserProfile() {
84
85
  ### 4. 使用社交登录
85
86
 
86
87
  ```tsx
87
- import { SocialLogin } from 'react-social-auth';
88
+ import { SocialLogin } from 'react-unified-auth';
88
89
 
89
90
  function SocialLoginPage() {
90
91
  const providers = [
@@ -224,9 +225,76 @@ const { formConfig, loading, error } = useDynamicForm(formId);
224
225
 
225
226
  组件使用了Tailwind CSS的类名,你可以通过以下方式自定义样式:
226
227
 
227
- 1. 在你的项目中配置Tailwind CSS
228
- 2. 通过`className` prop传递自定义类名
229
- 3. 覆盖默认样式
228
+ ### 1. 基本配置
229
+
230
+ 确保你的项目中已正确配置Tailwind CSS:
231
+
232
+ ```bash
233
+ # 安装依赖
234
+ npm install -D tailwindcss postcss autoprefixer
235
+
236
+ # 初始化配置
237
+ npx tailwindcss init -p
238
+ ```
239
+
240
+ ### 2. 更新tailwind.config.js
241
+
242
+ 在配置中包含组件库的文件路径:
243
+
244
+ ```js
245
+ // tailwind.config.js
246
+ module.exports = {
247
+ content: [
248
+ "./src/**/*.{js,ts,jsx,tsx}",
249
+ "./node_modules/react-unified-auth/dist/**/*.{js,ts,jsx,tsx}", // 必须包含此行
250
+ ],
251
+ theme: {
252
+ extend: {},
253
+ },
254
+ plugins: [],
255
+ }
256
+ ```
257
+
258
+ ### 3. 导入Tailwind CSS
259
+
260
+ 在项目入口文件中导入:
261
+
262
+ ```css
263
+ /* src/index.css */
264
+ @tailwind base;
265
+ @tailwind components;
266
+ @tailwind utilities;
267
+ ```
268
+
269
+ ```jsx
270
+ // src/index.jsx
271
+ import './index.css';
272
+ ```
273
+
274
+ ### 4. 自定义样式
275
+
276
+ - **通过className覆盖**:
277
+ ```jsx
278
+ <Button className="bg-red-600 hover:bg-red-700" />
279
+ ```
280
+
281
+ - **在Tailwind配置中扩展**:
282
+ ```js
283
+ // tailwind.config.js
284
+ module.exports = {
285
+ theme: {
286
+ extend: {
287
+ colors: {
288
+ primary: '#1d4ed8',
289
+ },
290
+ },
291
+ },
292
+ }
293
+ ```
294
+
295
+ ### 5. 样式不生效?查看详细排查指南
296
+
297
+ 如果样式仍然不生效,请查看我们的[Tailwind CSS样式排查指南](docs/TAILWIND_TROUBLESHOOTING.md),包含完整的问题解决步骤!
230
298
 
231
299
  ## 开发
232
300
 
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
3
+ variant?: 'primary' | 'secondary' | 'outline';
4
+ size?: 'sm' | 'md' | 'lg';
5
+ loading?: boolean;
6
+ fullWidth?: boolean;
7
+ }
8
+ export declare function Button({ variant, size, loading, fullWidth, children, disabled, className, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { FormField } from '../types';
2
+ export interface DynamicFormProps {
3
+ fields: FormField[];
4
+ onSubmit: (values: Record<string, any>) => void;
5
+ submitText?: string;
6
+ submitVariant?: 'primary' | 'secondary' | 'outline';
7
+ loading?: boolean;
8
+ }
9
+ export declare function DynamicForm({ fields, onSubmit, submitText, submitVariant, loading, }: DynamicFormProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ export interface LoginFormProps {
2
+ formId: string;
3
+ onSuccess?: (data: any) => void;
4
+ onError?: (error: string) => void;
5
+ }
6
+ export declare function LoginForm({ formId, onSuccess, onError }: LoginFormProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,15 @@
1
+ import { SocialProvider } from '../types';
2
+ export interface SocialLoginButtonProps {
3
+ provider: SocialProvider;
4
+ onClick: (provider: SocialProvider) => void;
5
+ loading?: boolean;
6
+ className?: string;
7
+ }
8
+ export declare function SocialLoginButton({ provider, onClick, loading, className }: SocialLoginButtonProps): import("react/jsx-runtime").JSX.Element;
9
+ export interface SocialLoginProps {
10
+ providers: SocialProvider[];
11
+ onLogin: (provider: SocialProvider) => void;
12
+ loading?: boolean;
13
+ className?: string;
14
+ }
15
+ export declare function SocialLogin({ providers, onLogin, loading, className }: SocialLoginProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,8 @@
1
+ import { UserInfo } from '../types';
2
+ export interface UserInfoBoxProps {
3
+ user: UserInfo;
4
+ onLogout?: () => void;
5
+ loading?: boolean;
6
+ className?: string;
7
+ }
8
+ export declare function UserInfoBox({ user, onLogout, loading, className }: UserInfoBoxProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { ReactNode } from 'react';
2
+ import { AuthConfig } from '../types';
3
+ export interface AuthProviderProps {
4
+ config: AuthConfig;
5
+ children: ReactNode;
6
+ }
7
+ export declare function AuthProvider({ config, children }: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function useAuthConfig(): AuthConfig;
@@ -0,0 +1,10 @@
1
+ import { AuthResponse, UserInfo } from '../types';
2
+ export declare function useAuth(): {
3
+ user: UserInfo | null;
4
+ loading: boolean;
5
+ error: string | null;
6
+ login: (credentials: Record<string, any>) => Promise<AuthResponse>;
7
+ logout: () => Promise<void>;
8
+ getUserInfo: () => Promise<UserInfo | null>;
9
+ isAuthenticated: boolean;
10
+ };
@@ -0,0 +1,6 @@
1
+ import { DynamicFormConfig } from '../types';
2
+ export declare function useDynamicForm(formId: string): {
3
+ formConfig: DynamicFormConfig | null;
4
+ loading: boolean;
5
+ error: string | null;
6
+ };
package/dist/index.css ADDED
@@ -0,0 +1,438 @@
1
+ /* Reset and base styles */
2
+ * {
3
+ box-sizing: border-box;
4
+ margin: 0;
5
+ padding: 0;
6
+ }
7
+
8
+ /* Button component styles */
9
+ .usa-button {
10
+ display: inline-flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ font-weight: 500;
14
+ border-radius: 8px;
15
+ transition: all 0.2s ease;
16
+ border: none;
17
+ cursor: pointer;
18
+ outline: none;
19
+ }
20
+
21
+ .usa-button:disabled {
22
+ opacity: 0.5;
23
+ cursor: not-allowed;
24
+ }
25
+
26
+ .usa-button:focus {
27
+ outline: none;
28
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.5);
29
+ }
30
+
31
+ /* Button variants */
32
+ .usa-button--primary {
33
+ background-color: #2563eb;
34
+ color: white;
35
+ }
36
+
37
+ .usa-button--primary:hover:not(:disabled) {
38
+ background-color: #1d4ed8;
39
+ }
40
+
41
+ .usa-button--secondary {
42
+ background-color: #6b7280;
43
+ color: white;
44
+ }
45
+
46
+ .usa-button--secondary:hover:not(:disabled) {
47
+ background-color: #4b5563;
48
+ }
49
+
50
+ .usa-button--outline {
51
+ border: 2px solid #2563eb;
52
+ background-color: transparent;
53
+ color: #2563eb;
54
+ }
55
+
56
+ .usa-button--outline:hover:not(:disabled) {
57
+ background-color: rgba(37, 99, 235, 0.1);
58
+ }
59
+
60
+ /* Button sizes */
61
+ .usa-button--sm {
62
+ padding: 0.375rem 0.75rem;
63
+ font-size: 0.875rem;
64
+ }
65
+
66
+ .usa-button--md {
67
+ padding: 0.5rem 1rem;
68
+ font-size: 1rem;
69
+ }
70
+
71
+ .usa-button--lg {
72
+ padding: 0.75rem 1.5rem;
73
+ font-size: 1.125rem;
74
+ }
75
+
76
+ .usa-button--full-width {
77
+ width: 100%;
78
+ }
79
+
80
+ /* Loading spinner */
81
+ .usa-loading-spinner {
82
+ display: inline-block;
83
+ width: 1rem;
84
+ height: 1rem;
85
+ border: 2px solid rgba(255, 255, 255, 0.3);
86
+ border-radius: 50%;
87
+ border-top-color: #fff;
88
+ animation: spin 0.8s linear infinite;
89
+ margin-right: 0.5rem;
90
+ }
91
+
92
+ .usa-button--outline .usa-loading-spinner {
93
+ border-color: rgba(37, 99, 235, 0.3);
94
+ border-top-color: #2563eb;
95
+ }
96
+
97
+ @keyframes spin {
98
+ to { transform: rotate(360deg); }
99
+ }
100
+
101
+ /* DynamicForm component styles */
102
+ .usa-form {
103
+ display: flex;
104
+ flex-direction: column;
105
+ gap: 1rem;
106
+ }
107
+
108
+ .usa-form__field-group {
109
+ display: flex;
110
+ flex-direction: column;
111
+ gap: 0.25rem;
112
+ }
113
+
114
+ .usa-form__label {
115
+ font-size: 0.875rem;
116
+ font-weight: 500;
117
+ color: #374151;
118
+ }
119
+
120
+ .usa-form__label--required::after {
121
+ content: " *";
122
+ color: #dc2626;
123
+ }
124
+
125
+ .usa-form__input {
126
+ width: 100%;
127
+ padding: 0.5rem 0.75rem;
128
+ border: 1px solid #d1d5db;
129
+ border-radius: 8px;
130
+ font-size: 1rem;
131
+ transition: all 0.2s ease;
132
+ }
133
+
134
+ .usa-form__input:focus {
135
+ outline: none;
136
+ border-color: #2563eb;
137
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
138
+ }
139
+
140
+ .usa-form__input--error {
141
+ border-color: #dc2626;
142
+ }
143
+
144
+ .usa-form__input--error:focus {
145
+ border-color: #dc2626;
146
+ box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);
147
+ }
148
+
149
+ .usa-form__textarea {
150
+ width: 100%;
151
+ padding: 0.5rem 0.75rem;
152
+ border: 1px solid #d1d5db;
153
+ border-radius: 8px;
154
+ font-size: 1rem;
155
+ font-family: inherit;
156
+ resize: vertical;
157
+ transition: all 0.2s ease;
158
+ }
159
+
160
+ .usa-form__textarea:focus {
161
+ outline: none;
162
+ border-color: #2563eb;
163
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
164
+ }
165
+
166
+ .usa-form__select {
167
+ width: 100%;
168
+ padding: 0.5rem 0.75rem;
169
+ border: 1px solid #d1d5db;
170
+ border-radius: 8px;
171
+ font-size: 1rem;
172
+ background-color: white;
173
+ cursor: pointer;
174
+ transition: all 0.2s ease;
175
+ }
176
+
177
+ .usa-form__select:focus {
178
+ outline: none;
179
+ border-color: #2563eb;
180
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
181
+ }
182
+
183
+ .usa-form__checkbox {
184
+ width: 1rem;
185
+ height: 1rem;
186
+ border: 1px solid #d1d5db;
187
+ border-radius: 4px;
188
+ accent-color: #2563eb;
189
+ cursor: pointer;
190
+ }
191
+
192
+ .usa-form__radio {
193
+ width: 1rem;
194
+ height: 1rem;
195
+ border: 1px solid #d1d5db;
196
+ border-radius: 50%;
197
+ accent-color: #2563eb;
198
+ cursor: pointer;
199
+ }
200
+
201
+ .usa-form__radio-group {
202
+ display: flex;
203
+ flex-direction: column;
204
+ gap: 0.5rem;
205
+ }
206
+
207
+ .usa-form__radio-label {
208
+ display: flex;
209
+ align-items: center;
210
+ gap: 0.5rem;
211
+ cursor: pointer;
212
+ }
213
+
214
+ .usa-form__error {
215
+ font-size: 0.75rem;
216
+ color: #dc2626;
217
+ }
218
+
219
+ /* LoginForm component styles */
220
+ .usa-login-form {
221
+ width: 100%;
222
+ }
223
+
224
+ .usa-login-form__loading {
225
+ display: flex;
226
+ justify-content: center;
227
+ align-items: center;
228
+ padding: 2rem;
229
+ }
230
+
231
+ .usa-login-form__error {
232
+ padding: 1rem;
233
+ background-color: #fee2e2;
234
+ border: 1px solid #fecaca;
235
+ border-radius: 8px;
236
+ color: #b91c1c;
237
+ }
238
+
239
+ /* UserInfoBox component styles */
240
+ .usa-user-info-box {
241
+ background-color: white;
242
+ border-radius: 8px;
243
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
244
+ padding: 1.5rem;
245
+ }
246
+
247
+ .usa-user-info-box__header {
248
+ display: flex;
249
+ align-items: center;
250
+ gap: 1rem;
251
+ margin-bottom: 1rem;
252
+ }
253
+
254
+ .usa-user-info-box__avatar {
255
+ width: 4rem;
256
+ height: 4rem;
257
+ border-radius: 50%;
258
+ object-fit: cover;
259
+ }
260
+
261
+ .usa-user-info-box__details {
262
+ flex: 1;
263
+ }
264
+
265
+ .usa-user-info-box__name {
266
+ font-size: 1.125rem;
267
+ font-weight: 600;
268
+ color: #111827;
269
+ }
270
+
271
+ .usa-user-info-box__email {
272
+ font-size: 0.875rem;
273
+ color: #6b7280;
274
+ }
275
+
276
+ /* SocialLogin component styles */
277
+ .usa-social-login {
278
+ display: flex;
279
+ flex-direction: column;
280
+ gap: 0.75rem;
281
+ }
282
+
283
+ .usa-social-login-button {
284
+ display: flex;
285
+ align-items: center;
286
+ justify-content: center;
287
+ gap: 0.5rem;
288
+ }
289
+
290
+ .usa-social-login-button__icon {
291
+ width: 1.25rem;
292
+ height: 1.25rem;
293
+ }
294
+
295
+ /* Utility classes */
296
+ .usa-text-center {
297
+ text-align: center;
298
+ }
299
+
300
+ .usa-mt-4 {
301
+ margin-top: 1rem;
302
+ }
303
+
304
+ .usa-mb-4 {
305
+ margin-bottom: 1rem;
306
+ }
307
+
308
+ .usa-mb-8 {
309
+ margin-bottom: 2rem;
310
+ }
311
+
312
+ .usa-w-full {
313
+ width: 100%;
314
+ }
315
+
316
+ .usa-flex {
317
+ display: flex;
318
+ }
319
+
320
+ .usa-flex-col {
321
+ flex-direction: column;
322
+ }
323
+
324
+ .usa-items-center {
325
+ align-items: center;
326
+ }
327
+
328
+ .usa-justify-center {
329
+ justify-content: center;
330
+ }
331
+
332
+ .usa-space-x-2 {
333
+ gap: 0.5rem;
334
+ }
335
+
336
+ .usa-space-y-2 {
337
+ gap: 0.5rem;
338
+ }
339
+
340
+ .usa-space-y-3 {
341
+ gap: 0.75rem;
342
+ }
343
+
344
+ .usa-space-y-4 {
345
+ gap: 1rem;
346
+ }
347
+
348
+ .usa-space-y-6 {
349
+ gap: 1.5rem;
350
+ }
351
+
352
+ .usa-space-y-8 {
353
+ gap: 2rem;
354
+ }
355
+
356
+ .usa-p-6 {
357
+ padding: 1.5rem;
358
+ }
359
+
360
+ .usa-pt-6 {
361
+ padding-top: 1.5rem;
362
+ }
363
+
364
+ .usa-bg-white {
365
+ background-color: white;
366
+ }
367
+
368
+ .usa-bg-gray-100 {
369
+ background-color: #f3f4f6;
370
+ }
371
+
372
+ .usa-bg-red-50 {
373
+ background-color: #fee2e2;
374
+ }
375
+
376
+ .usa-text-lg {
377
+ font-size: 1.125rem;
378
+ }
379
+
380
+ .usa-text-xl {
381
+ font-size: 1.25rem;
382
+ }
383
+
384
+ .usa-text-2xl {
385
+ font-size: 1.5rem;
386
+ }
387
+
388
+ .usa-text-3xl {
389
+ font-size: 1.875rem;
390
+ }
391
+
392
+ .usa-font-bold {
393
+ font-weight: 700;
394
+ }
395
+
396
+ .usa-font-semibold {
397
+ font-weight: 600;
398
+ }
399
+
400
+ .usa-text-gray-600 {
401
+ color: #6b7280;
402
+ }
403
+
404
+ .usa-text-gray-900 {
405
+ color: #111827;
406
+ }
407
+
408
+ .usa-text-red-600 {
409
+ color: #dc2626;
410
+ }
411
+
412
+ .usa-border-t {
413
+ border-top: 1px solid #e5e7eb;
414
+ }
415
+
416
+ .usa-border {
417
+ border: 1px solid #e5e7eb;
418
+ }
419
+
420
+ .usa-border-red-200 {
421
+ border-color: #fecaca;
422
+ }
423
+
424
+ .usa-rounded-lg {
425
+ border-radius: 8px;
426
+ }
427
+
428
+ .usa-rounded-full {
429
+ border-radius: 50%;
430
+ }
431
+
432
+ .usa-shadow-md {
433
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
434
+ }
435
+
436
+ .usa-shadow-lg {
437
+ box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
438
+ }