@drawboard/authagonal-login 0.1.1

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/src/styles.css ADDED
@@ -0,0 +1,339 @@
1
+ :root {
2
+ --color-primary: #2563eb;
3
+ }
4
+
5
+ *,
6
+ *::before,
7
+ *::after {
8
+ box-sizing: border-box;
9
+ margin: 0;
10
+ padding: 0;
11
+ }
12
+
13
+ body {
14
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
15
+ 'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
16
+ background-color: #f3f4f6;
17
+ color: #111827;
18
+ line-height: 1.5;
19
+ -webkit-font-smoothing: antialiased;
20
+ -moz-osx-font-smoothing: grayscale;
21
+ }
22
+
23
+ /* Layout */
24
+ .auth-container {
25
+ min-height: 100vh;
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ padding: 16px;
30
+ }
31
+
32
+ .auth-card {
33
+ width: 100%;
34
+ max-width: 420px;
35
+ background: #ffffff;
36
+ border-radius: 8px;
37
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
38
+ padding: 32px;
39
+ }
40
+
41
+ .auth-logo {
42
+ text-align: center;
43
+ margin-bottom: 24px;
44
+ }
45
+
46
+ .auth-logo h1 {
47
+ font-size: 24px;
48
+ font-weight: 700;
49
+ color: #111827;
50
+ letter-spacing: -0.025em;
51
+ }
52
+
53
+ .auth-logo-img {
54
+ max-height: 48px;
55
+ max-width: 100%;
56
+ object-fit: contain;
57
+ }
58
+
59
+ .auth-title {
60
+ font-size: 20px;
61
+ font-weight: 600;
62
+ color: #111827;
63
+ margin-bottom: 8px;
64
+ }
65
+
66
+ .auth-subtitle {
67
+ font-size: 14px;
68
+ color: #6b7280;
69
+ margin-bottom: 20px;
70
+ }
71
+
72
+ /* Form */
73
+ .form-group {
74
+ margin-bottom: 16px;
75
+ }
76
+
77
+ .form-group label {
78
+ display: block;
79
+ font-size: 14px;
80
+ font-weight: 500;
81
+ color: #374151;
82
+ margin-bottom: 6px;
83
+ }
84
+
85
+ input {
86
+ width: 100%;
87
+ padding: 12px;
88
+ border: 1px solid #d1d5db;
89
+ border-radius: 6px;
90
+ font-size: 16px;
91
+ color: #111827;
92
+ background-color: #ffffff;
93
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
94
+ }
95
+
96
+ input::placeholder {
97
+ color: #9ca3af;
98
+ }
99
+
100
+ input:focus {
101
+ outline: none;
102
+ border-color: var(--color-primary);
103
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 15%, transparent);
104
+ }
105
+
106
+ /* Buttons */
107
+ .btn-primary {
108
+ display: block;
109
+ width: 100%;
110
+ padding: 12px;
111
+ background-color: var(--color-primary);
112
+ color: #ffffff;
113
+ border: none;
114
+ border-radius: 6px;
115
+ font-size: 16px;
116
+ font-weight: 500;
117
+ cursor: pointer;
118
+ transition: background-color 0.15s ease;
119
+ text-align: center;
120
+ }
121
+
122
+ .btn-primary:hover:not(:disabled) {
123
+ background-color: color-mix(in srgb, var(--color-primary) 85%, black);
124
+ }
125
+
126
+ .btn-primary:disabled {
127
+ opacity: 0.5;
128
+ cursor: not-allowed;
129
+ }
130
+
131
+ .btn-secondary {
132
+ display: block;
133
+ width: 100%;
134
+ padding: 12px;
135
+ background-color: #ffffff;
136
+ color: #374151;
137
+ border: 1px solid #d1d5db;
138
+ border-radius: 6px;
139
+ font-size: 16px;
140
+ font-weight: 500;
141
+ cursor: pointer;
142
+ transition: background-color 0.15s ease, border-color 0.15s ease;
143
+ text-align: center;
144
+ }
145
+
146
+ .btn-secondary:hover {
147
+ background-color: #f9fafb;
148
+ border-color: #9ca3af;
149
+ }
150
+
151
+ .btn-loading {
152
+ display: inline-flex;
153
+ align-items: center;
154
+ justify-content: center;
155
+ gap: 8px;
156
+ }
157
+
158
+ .spinner {
159
+ display: inline-block;
160
+ width: 16px;
161
+ height: 16px;
162
+ border: 2px solid rgba(255, 255, 255, 0.3);
163
+ border-top-color: #ffffff;
164
+ border-radius: 50%;
165
+ animation: spin 0.6s linear infinite;
166
+ }
167
+
168
+ @keyframes spin {
169
+ to {
170
+ transform: rotate(360deg);
171
+ }
172
+ }
173
+
174
+ /* Alerts */
175
+ .alert-error {
176
+ background-color: #fef2f2;
177
+ color: #991b1b;
178
+ border: 1px solid #fecaca;
179
+ border-radius: 6px;
180
+ padding: 12px;
181
+ font-size: 14px;
182
+ margin-bottom: 16px;
183
+ }
184
+
185
+ .alert-success {
186
+ background-color: #f0fdf4;
187
+ color: #166534;
188
+ border: 1px solid #bbf7d0;
189
+ border-radius: 6px;
190
+ padding: 12px;
191
+ font-size: 14px;
192
+ margin-bottom: 16px;
193
+ }
194
+
195
+ /* Links */
196
+ .link {
197
+ color: var(--color-primary);
198
+ text-decoration: none;
199
+ font-size: 14px;
200
+ font-weight: 500;
201
+ }
202
+
203
+ .link:hover {
204
+ text-decoration: underline;
205
+ }
206
+
207
+ .form-footer {
208
+ margin-top: 16px;
209
+ text-align: center;
210
+ }
211
+
212
+ /* SSO */
213
+ .sso-notice {
214
+ margin-bottom: 16px;
215
+ }
216
+
217
+ .sso-notice p {
218
+ font-size: 14px;
219
+ color: #6b7280;
220
+ margin-bottom: 12px;
221
+ }
222
+
223
+ .sso-checking {
224
+ font-size: 14px;
225
+ color: #6b7280;
226
+ margin-bottom: 16px;
227
+ }
228
+
229
+ /* External providers */
230
+ .external-providers {
231
+ margin-bottom: 8px;
232
+ }
233
+
234
+ .btn-provider {
235
+ display: flex;
236
+ align-items: center;
237
+ justify-content: center;
238
+ gap: 10px;
239
+ width: 100%;
240
+ padding: 12px;
241
+ background-color: #ffffff;
242
+ color: #374151;
243
+ border: 1px solid #d1d5db;
244
+ border-radius: 6px;
245
+ font-size: 16px;
246
+ font-weight: 500;
247
+ cursor: pointer;
248
+ transition: background-color 0.15s ease, border-color 0.15s ease;
249
+ margin-bottom: 8px;
250
+ }
251
+
252
+ .btn-provider:hover {
253
+ background-color: #f9fafb;
254
+ border-color: #9ca3af;
255
+ }
256
+
257
+ .provider-icon {
258
+ flex-shrink: 0;
259
+ }
260
+
261
+ .divider {
262
+ display: flex;
263
+ align-items: center;
264
+ gap: 12px;
265
+ margin: 16px 0;
266
+ color: #9ca3af;
267
+ font-size: 13px;
268
+ }
269
+
270
+ .divider::before,
271
+ .divider::after {
272
+ content: '';
273
+ flex: 1;
274
+ height: 1px;
275
+ background-color: #e5e7eb;
276
+ }
277
+
278
+ /* Language picker */
279
+ .language-picker {
280
+ display: flex;
281
+ flex-wrap: wrap;
282
+ justify-content: center;
283
+ gap: 4px;
284
+ margin-top: 24px;
285
+ padding-top: 16px;
286
+ border-top: 1px solid #e5e7eb;
287
+ }
288
+
289
+ .language-btn {
290
+ background: none;
291
+ border: none;
292
+ padding: 4px 8px;
293
+ font-size: 12px;
294
+ color: #9ca3af;
295
+ cursor: pointer;
296
+ border-radius: 4px;
297
+ }
298
+
299
+ .language-btn:hover {
300
+ color: #374151;
301
+ background-color: #f3f4f6;
302
+ }
303
+
304
+ .language-btn.active {
305
+ color: var(--color-primary);
306
+ font-weight: 600;
307
+ }
308
+
309
+ /* Password requirements */
310
+ .password-requirements {
311
+ list-style: none;
312
+ margin-bottom: 16px;
313
+ padding: 12px;
314
+ background-color: #f9fafb;
315
+ border-radius: 6px;
316
+ }
317
+
318
+ .password-requirements li {
319
+ font-size: 13px;
320
+ padding: 2px 0;
321
+ display: flex;
322
+ align-items: center;
323
+ gap: 6px;
324
+ }
325
+
326
+ .password-requirements li.met {
327
+ color: #166534;
328
+ }
329
+
330
+ .password-requirements li.unmet {
331
+ color: #991b1b;
332
+ }
333
+
334
+ .password-requirements .req-icon {
335
+ font-size: 12px;
336
+ width: 16px;
337
+ text-align: center;
338
+ flex-shrink: 0;
339
+ }
package/src/types.ts ADDED
@@ -0,0 +1,46 @@
1
+ export interface LoginResponse {
2
+ userId: string;
3
+ email: string;
4
+ name: string;
5
+ }
6
+
7
+ export interface ApiError {
8
+ error: string;
9
+ message?: string;
10
+ retryAfter?: number;
11
+ redirectUrl?: string;
12
+ }
13
+
14
+ export interface SessionResponse {
15
+ authenticated: boolean;
16
+ userId: string;
17
+ email: string;
18
+ name: string;
19
+ }
20
+
21
+ export interface SsoCheckResponse {
22
+ ssoRequired: boolean;
23
+ providerType?: string;
24
+ connectionId?: string;
25
+ redirectUrl?: string;
26
+ }
27
+
28
+ export interface ExternalProvider {
29
+ connectionId: string;
30
+ name: string;
31
+ loginUrl: string;
32
+ }
33
+
34
+ export interface ProvidersResponse {
35
+ providers: ExternalProvider[];
36
+ }
37
+
38
+ export interface PasswordPolicyRule {
39
+ rule: string;
40
+ value: number | null;
41
+ label: string;
42
+ }
43
+
44
+ export interface PasswordPolicyResponse {
45
+ rules: PasswordPolicyRule[];
46
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2023",
5
+ "useDefineForClassFields": true,
6
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "types": ["vite/client"],
9
+ "skipLibCheck": true,
10
+
11
+ /* Bundler mode */
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "verbatimModuleSyntax": true,
15
+ "moduleDetection": "force",
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+
19
+ /* Linting */
20
+ "strict": true,
21
+ "noUnusedLocals": true,
22
+ "noUnusedParameters": true,
23
+ "erasableSyntaxOnly": true,
24
+ "noFallthroughCasesInSwitch": true,
25
+ "noUncheckedSideEffectImports": true
26
+ },
27
+ "include": ["src"]
28
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ // https://vite.dev/config/
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ server: {
8
+ proxy: {
9
+ '/api': {
10
+ target: 'http://localhost:5000',
11
+ changeOrigin: true,
12
+ },
13
+ '/saml': {
14
+ target: 'http://localhost:5000',
15
+ changeOrigin: true,
16
+ },
17
+ '/oidc': {
18
+ target: 'http://localhost:5000',
19
+ changeOrigin: true,
20
+ },
21
+ '/connect': {
22
+ target: 'http://localhost:5000',
23
+ changeOrigin: true,
24
+ },
25
+ },
26
+ },
27
+ })