@draftlab/auth 0.0.4 → 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/dist/error.d.ts +1 -1
- package/dist/provider/code.d.ts +26 -10
- package/dist/provider/code.js +26 -13
- package/dist/provider/password.d.ts +2 -2
- package/dist/storage/memory.d.ts +1 -1
- package/dist/storage/unstorage.d.ts +1 -1
- package/dist/storage/unstorage.js +1 -1
- package/dist/themes/theme.d.ts +2 -2
- package/dist/ui/base.d.ts +22 -35
- package/dist/ui/base.js +163 -177
- package/dist/ui/code.d.ts +22 -135
- package/dist/ui/code.js +199 -160
- package/dist/ui/form.d.ts +8 -6
- package/dist/ui/form.js +44 -46
- package/dist/ui/icon.d.ts +7 -84
- package/dist/ui/icon.js +56 -178
- package/dist/ui/password.d.ts +29 -34
- package/dist/ui/password.js +340 -236
- package/dist/ui/select.d.ts +19 -218
- package/dist/ui/select.js +72 -259
- package/package.json +4 -2
package/dist/error.d.ts
CHANGED
package/dist/provider/code.d.ts
CHANGED
|
@@ -67,8 +67,8 @@ interface CodeProviderConfig<Claims extends Record<string, string> = Record<stri
|
|
|
67
67
|
* } else {
|
|
68
68
|
* return {
|
|
69
69
|
* type: "invalid_claim",
|
|
70
|
-
* key: "
|
|
71
|
-
* value: "
|
|
70
|
+
* key: "email",
|
|
71
|
+
* value: "Email or phone number is required"
|
|
72
72
|
* }
|
|
73
73
|
* }
|
|
74
74
|
* } catch (error) {
|
|
@@ -152,7 +152,15 @@ interface CodeUserData<Claims extends Record<string, string> = Record<string, st
|
|
|
152
152
|
* }
|
|
153
153
|
* }
|
|
154
154
|
*
|
|
155
|
-
*
|
|
155
|
+
* try {
|
|
156
|
+
* await emailService.send(claims.email, `Your verification code: ${code}`)
|
|
157
|
+
* } catch {
|
|
158
|
+
* return {
|
|
159
|
+
* type: "invalid_claim",
|
|
160
|
+
* key: "delivery",
|
|
161
|
+
* value: "Failed to send code"
|
|
162
|
+
* }
|
|
163
|
+
* }
|
|
156
164
|
* }
|
|
157
165
|
* })
|
|
158
166
|
*
|
|
@@ -168,15 +176,23 @@ interface CodeUserData<Claims extends Record<string, string> = Record<string, st
|
|
|
168
176
|
* }
|
|
169
177
|
* },
|
|
170
178
|
* sendCode: async (claims, code) => {
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
179
|
+
* try {
|
|
180
|
+
* if (claims.email) {
|
|
181
|
+
* await emailService.send(claims.email, `PIN: ${code}`)
|
|
182
|
+
* } else if (claims.phone) {
|
|
183
|
+
* await smsService.send(claims.phone, `PIN: ${code}`)
|
|
184
|
+
* } else {
|
|
185
|
+
* return {
|
|
186
|
+
* type: "invalid_claim",
|
|
187
|
+
* key: "email",
|
|
188
|
+
* value: "Provide either email or phone number"
|
|
189
|
+
* }
|
|
190
|
+
* }
|
|
191
|
+
* } catch {
|
|
176
192
|
* return {
|
|
177
193
|
* type: "invalid_claim",
|
|
178
|
-
* key: "
|
|
179
|
-
* value: "
|
|
194
|
+
* key: "delivery",
|
|
195
|
+
* value: "Failed to send code"
|
|
180
196
|
* }
|
|
181
197
|
* }
|
|
182
198
|
* }
|
package/dist/provider/code.js
CHANGED
|
@@ -30,7 +30,15 @@ import { generateUnbiasedDigits, timingSafeCompare } from "../random.js";
|
|
|
30
30
|
* }
|
|
31
31
|
* }
|
|
32
32
|
*
|
|
33
|
-
*
|
|
33
|
+
* try {
|
|
34
|
+
* await emailService.send(claims.email, `Your verification code: ${code}`)
|
|
35
|
+
* } catch {
|
|
36
|
+
* return {
|
|
37
|
+
* type: "invalid_claim",
|
|
38
|
+
* key: "delivery",
|
|
39
|
+
* value: "Failed to send code"
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
34
42
|
* }
|
|
35
43
|
* })
|
|
36
44
|
*
|
|
@@ -46,15 +54,23 @@ import { generateUnbiasedDigits, timingSafeCompare } from "../random.js";
|
|
|
46
54
|
* }
|
|
47
55
|
* },
|
|
48
56
|
* sendCode: async (claims, code) => {
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
57
|
+
* try {
|
|
58
|
+
* if (claims.email) {
|
|
59
|
+
* await emailService.send(claims.email, `PIN: ${code}`)
|
|
60
|
+
* } else if (claims.phone) {
|
|
61
|
+
* await smsService.send(claims.phone, `PIN: ${code}`)
|
|
62
|
+
* } else {
|
|
63
|
+
* return {
|
|
64
|
+
* type: "invalid_claim",
|
|
65
|
+
* key: "email",
|
|
66
|
+
* value: "Provide either email or phone number"
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
* } catch {
|
|
54
70
|
* return {
|
|
55
71
|
* type: "invalid_claim",
|
|
56
|
-
* key: "
|
|
57
|
-
* value: "
|
|
72
|
+
* key: "delivery",
|
|
73
|
+
* value: "Failed to send code"
|
|
58
74
|
* }
|
|
59
75
|
* }
|
|
60
76
|
* }
|
|
@@ -124,18 +140,15 @@ const CodeProvider = (config) => {
|
|
|
124
140
|
claims,
|
|
125
141
|
code
|
|
126
142
|
}, formData);
|
|
127
|
-
}
|
|
128
|
-
if (action === "verify" && currentState?.type === "code") {
|
|
143
|
+
} else if (action === "verify" && currentState?.type === "code") {
|
|
129
144
|
const enteredCode = formData.get("code")?.toString();
|
|
130
145
|
if (!(currentState.code && enteredCode && timingSafeCompare(currentState.code, enteredCode))) return transition(c, {
|
|
131
146
|
...currentState,
|
|
132
147
|
resend: false
|
|
133
148
|
}, formData, { type: "invalid_code" });
|
|
134
149
|
await ctx.unset(c, "provider");
|
|
135
|
-
|
|
136
|
-
return ctx.forward(c, successResponse);
|
|
150
|
+
return await ctx.success(c, { claims: currentState.claims });
|
|
137
151
|
}
|
|
138
|
-
return transition(c, { type: "start" }, formData);
|
|
139
152
|
});
|
|
140
153
|
}
|
|
141
154
|
};
|
|
@@ -10,8 +10,8 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
|
10
10
|
* ## Quick Setup
|
|
11
11
|
*
|
|
12
12
|
* ```ts
|
|
13
|
-
* import { PasswordUI } from "@
|
|
14
|
-
* import { PasswordProvider } from "@
|
|
13
|
+
* import { PasswordUI } from "@draftlab/auth/ui/password"
|
|
14
|
+
* import { PasswordProvider } from "@draftlab/auth/provider/password"
|
|
15
15
|
*
|
|
16
16
|
* export default issuer({
|
|
17
17
|
* providers: {
|
package/dist/storage/memory.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { StorageAdapter } from "./storage.js";
|
|
|
9
9
|
*
|
|
10
10
|
* ### Basic in-memory storage (development only)
|
|
11
11
|
* ```ts
|
|
12
|
-
* import { MemoryStorage } from "@
|
|
12
|
+
* import { MemoryStorage } from "@draftlab/auth/storage/memory"
|
|
13
13
|
*
|
|
14
14
|
* const storage = MemoryStorage()
|
|
15
15
|
*
|
|
@@ -13,7 +13,7 @@ import { Driver } from "unstorage";
|
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* ```ts
|
|
16
|
-
* import { UnStorage } from "@
|
|
16
|
+
* import { UnStorage } from "@draftlab/auth/storage/unstorage"
|
|
17
17
|
* import redisDriver from "unstorage/drivers/redis"
|
|
18
18
|
*
|
|
19
19
|
* // Using Redis driver
|
|
@@ -12,7 +12,7 @@ import { createStorage } from "unstorage";
|
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
14
14
|
* ```ts
|
|
15
|
-
* import { UnStorage } from "@
|
|
15
|
+
* import { UnStorage } from "@draftlab/auth/storage/unstorage"
|
|
16
16
|
* import redisDriver from "unstorage/drivers/redis"
|
|
17
17
|
*
|
|
18
18
|
* // Using Redis driver
|
package/dist/themes/theme.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @example
|
|
6
6
|
*
|
|
7
7
|
* ```ts
|
|
8
|
-
* import { THEME_SST } from "@
|
|
8
|
+
* import { THEME_SST } from "@draftlab/auth/themes/theme"
|
|
9
9
|
*
|
|
10
10
|
* export default issuer({
|
|
11
11
|
* theme: THEME_SST,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Or define your own.
|
|
17
17
|
*
|
|
18
18
|
* ```ts
|
|
19
|
-
* import type { Theme } from "@
|
|
19
|
+
* import type { Theme } from "@draftlab/auth/themes/theme"
|
|
20
20
|
*
|
|
21
21
|
* const MY_THEME: Theme = {
|
|
22
22
|
* title: "Acne",
|
package/dist/ui/base.d.ts
CHANGED
|
@@ -1,43 +1,30 @@
|
|
|
1
|
+
import { Theme } from "../themes/theme.js";
|
|
2
|
+
import * as preact6 from "preact";
|
|
3
|
+
import { ComponentChildren } from "preact";
|
|
4
|
+
|
|
1
5
|
//#region src/ui/base.d.ts
|
|
2
|
-
|
|
3
|
-
children?: string;
|
|
4
|
-
};
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
7
|
-
* Provides theming, responsive design, and consistent styling across all auth screens.
|
|
8
|
-
*
|
|
9
|
-
* ## Features
|
|
10
|
-
*
|
|
11
|
-
* - **Theme Support**: Light/dark mode with custom colors and fonts
|
|
12
|
-
* - **Responsive Design**: Adapts to different screen sizes
|
|
13
|
-
* - **Custom Branding**: Support for custom logos and styling
|
|
14
|
-
* - **CSS Variables**: Uses CSS custom properties for theming
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```tsx
|
|
18
|
-
* <Layout size="small">
|
|
19
|
-
* <div>Your auth form content</div>
|
|
20
|
-
* </Layout>
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* Props for the Layout component.
|
|
8
|
+
* Props for the Layout component
|
|
25
9
|
*/
|
|
26
10
|
interface LayoutProps {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*/
|
|
32
|
-
readonly size?: "small";
|
|
11
|
+
children: ComponentChildren;
|
|
12
|
+
theme?: Theme;
|
|
13
|
+
title?: string;
|
|
14
|
+
size?: "small";
|
|
33
15
|
}
|
|
34
16
|
/**
|
|
35
|
-
*
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
17
|
+
* Base Layout component that provides the foundational structure for all auth UIs
|
|
18
|
+
*/
|
|
19
|
+
declare const Layout: ({
|
|
20
|
+
children,
|
|
21
|
+
theme,
|
|
22
|
+
title,
|
|
23
|
+
size
|
|
24
|
+
}: LayoutProps) => preact6.JSX.Element;
|
|
25
|
+
/**
|
|
26
|
+
* Helper function to render a Preact component to HTML string
|
|
40
27
|
*/
|
|
41
|
-
declare const
|
|
28
|
+
declare const renderToHTML: (component: ComponentChildren) => string;
|
|
42
29
|
//#endregion
|
|
43
|
-
export { Layout, LayoutProps };
|
|
30
|
+
export { Layout, LayoutProps, renderToHTML };
|
package/dist/ui/base.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getTheme } from "../themes/theme.js";
|
|
2
|
+
import { render } from "preact-render-to-string";
|
|
3
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
2
4
|
|
|
3
|
-
//#region src/ui/base.
|
|
5
|
+
//#region src/ui/base.tsx
|
|
4
6
|
const css = `@import url("https://unpkg.com/tailwindcss@3.4.15/src/css/preflight.css");
|
|
5
7
|
|
|
6
8
|
:root {
|
|
@@ -102,102 +104,6 @@ const css = `@import url("https://unpkg.com/tailwindcss@3.4.15/src/css/preflight
|
|
|
102
104
|
width: 300px;
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
[data-component="link"] {
|
|
106
|
-
text-decoration: underline;
|
|
107
|
-
text-underline-offset: 0.125rem;
|
|
108
|
-
font-weight: 600;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
[data-component="label"] {
|
|
112
|
-
display: flex;
|
|
113
|
-
gap: 0.75rem;
|
|
114
|
-
flex-direction: column;
|
|
115
|
-
font-size: var(--font-size-xs);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
[data-component="logo"] {
|
|
119
|
-
margin: 0 auto;
|
|
120
|
-
height: 2.5rem;
|
|
121
|
-
width: auto;
|
|
122
|
-
display: none;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
@media (prefers-color-scheme: light) {
|
|
126
|
-
[data-component="logo"][data-mode="light"] {
|
|
127
|
-
display: block;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
@media (prefers-color-scheme: dark) {
|
|
132
|
-
[data-component="logo"][data-mode="dark"] {
|
|
133
|
-
display: block;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
[data-component="logo-default"] {
|
|
138
|
-
margin: 0 auto;
|
|
139
|
-
height: 2.5rem;
|
|
140
|
-
width: auto;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
@media (prefers-color-scheme: light) {
|
|
144
|
-
[data-component="logo-default"] {
|
|
145
|
-
color: var(--color-high);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
@media (prefers-color-scheme: dark) {
|
|
150
|
-
[data-component="logo-default"] {
|
|
151
|
-
color: var(--color-high);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
[data-component="input"] {
|
|
156
|
-
width: 100%;
|
|
157
|
-
height: 2.5rem;
|
|
158
|
-
padding: 0 1rem;
|
|
159
|
-
border: 1px solid transparent;
|
|
160
|
-
--background: oklch(
|
|
161
|
-
from var(--color-background)
|
|
162
|
-
calc(l + (-0.06 * clamp(0, calc((l - 0.714) * 1000), 1) + 0.03)) c h
|
|
163
|
-
);
|
|
164
|
-
background: var(--background);
|
|
165
|
-
border-color: oklch(
|
|
166
|
-
from var(--color-background)
|
|
167
|
-
calc(
|
|
168
|
-
clamp(
|
|
169
|
-
0.22,
|
|
170
|
-
l +
|
|
171
|
-
(-0.12 * clamp(0, calc((l - 0.714) * 1000), 1) + 0.06),
|
|
172
|
-
0.88
|
|
173
|
-
)
|
|
174
|
-
)
|
|
175
|
-
c h
|
|
176
|
-
);
|
|
177
|
-
border-radius: calc(var(--border-radius) * 0.25rem);
|
|
178
|
-
font-size: var(--font-size-sm);
|
|
179
|
-
outline: none;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
[data-component="input"]:focus {
|
|
183
|
-
border-color: oklch(
|
|
184
|
-
from var(--color-background)
|
|
185
|
-
calc(
|
|
186
|
-
clamp(
|
|
187
|
-
0.3,
|
|
188
|
-
l +
|
|
189
|
-
(-0.2 * clamp(0, calc((l - 0.714) * 1000), 1) + 0.1),
|
|
190
|
-
0.7
|
|
191
|
-
)
|
|
192
|
-
)
|
|
193
|
-
c h
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
[data-component="input"]:user-invalid:not(:focus) {
|
|
198
|
-
border-color: oklch(0.4 0.09 7.91);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
107
|
[data-component="button"] {
|
|
202
108
|
height: 2.5rem;
|
|
203
109
|
cursor: pointer;
|
|
@@ -251,42 +157,93 @@ const css = `@import url("https://unpkg.com/tailwindcss@3.4.15/src/css/preflight
|
|
|
251
157
|
margin: 0;
|
|
252
158
|
}
|
|
253
159
|
|
|
254
|
-
[data-component="
|
|
160
|
+
[data-component="input"] {
|
|
255
161
|
height: 2.5rem;
|
|
162
|
+
border: 1px solid
|
|
163
|
+
oklch(
|
|
164
|
+
from var(--color-background)
|
|
165
|
+
calc(
|
|
166
|
+
clamp(
|
|
167
|
+
0.22,
|
|
168
|
+
l +
|
|
169
|
+
(-0.12 * clamp(0, calc((l - 0.714) * 1000), 1) + 0.06),
|
|
170
|
+
0.88
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
c h
|
|
174
|
+
);
|
|
175
|
+
border-radius: calc(var(--border-radius) * 0.25rem);
|
|
176
|
+
background: var(--color-background);
|
|
177
|
+
color: var(--color-high);
|
|
178
|
+
padding: 0 0.75rem;
|
|
179
|
+
font-size: var(--font-size-sm);
|
|
180
|
+
font-family: var(--font-family);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
[data-component="input"]:focus {
|
|
184
|
+
outline: none;
|
|
185
|
+
border-color: var(--color-primary);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
[data-component="input"]::placeholder {
|
|
189
|
+
color: oklch(
|
|
190
|
+
from var(--color-high)
|
|
191
|
+
l
|
|
192
|
+
c
|
|
193
|
+
h /
|
|
194
|
+
0.6
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
[data-component="form-alert"] {
|
|
199
|
+
padding: 0.75rem;
|
|
200
|
+
border-radius: calc(var(--border-radius) * 0.25rem);
|
|
256
201
|
display: flex;
|
|
257
202
|
align-items: center;
|
|
258
|
-
|
|
259
|
-
|
|
203
|
+
gap: 0.75rem;
|
|
204
|
+
font-size: var(--font-size-sm);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
[data-component="form-alert"][data-color="danger"] {
|
|
260
208
|
background: var(--color-background-error);
|
|
261
209
|
color: var(--color-error);
|
|
262
|
-
|
|
263
|
-
font-size: 0.75rem;
|
|
264
|
-
gap: 0.5rem;
|
|
210
|
+
border: 1px solid var(--color-error);
|
|
265
211
|
}
|
|
266
212
|
|
|
267
213
|
[data-component="form-alert"][data-color="success"] {
|
|
268
214
|
background: var(--color-background-success);
|
|
269
215
|
color: var(--color-success);
|
|
216
|
+
border: 1px solid var(--color-success);
|
|
270
217
|
}
|
|
271
218
|
|
|
272
|
-
[data-component="form-alert"]
|
|
273
|
-
display: block;
|
|
274
|
-
}
|
|
275
|
-
[data-component="form-alert"][data-color="success"] [data-slot="icon-danger"] {
|
|
219
|
+
[data-component="form-alert"] [data-slot="icon-success"] {
|
|
276
220
|
display: none;
|
|
277
221
|
}
|
|
278
222
|
|
|
279
|
-
[data-component="form-alert"]
|
|
223
|
+
[data-component="form-alert"] [data-slot="icon-danger"] {
|
|
280
224
|
display: none;
|
|
281
225
|
}
|
|
282
226
|
|
|
283
|
-
[data-component="form-alert"] [data-slot="icon-success"]
|
|
284
|
-
|
|
285
|
-
width:
|
|
286
|
-
height:
|
|
227
|
+
[data-component="form-alert"][data-color="success"] [data-slot="icon-success"] {
|
|
228
|
+
display: block;
|
|
229
|
+
width: 16px;
|
|
230
|
+
height: 16px;
|
|
287
231
|
}
|
|
288
|
-
|
|
289
|
-
|
|
232
|
+
|
|
233
|
+
[data-component="form-alert"][data-color="danger"] [data-slot="icon-danger"] {
|
|
234
|
+
display: block;
|
|
235
|
+
width: 16px;
|
|
236
|
+
height: 16px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
[data-component="link"] {
|
|
240
|
+
color: var(--color-primary);
|
|
241
|
+
text-decoration: none;
|
|
242
|
+
font-size: var(--font-size-sm);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
[data-component="link"]:hover {
|
|
246
|
+
text-decoration: underline;
|
|
290
247
|
}
|
|
291
248
|
|
|
292
249
|
[data-component="form-footer"] {
|
|
@@ -300,30 +257,62 @@ const css = `@import url("https://unpkg.com/tailwindcss@3.4.15/src/css/preflight
|
|
|
300
257
|
[data-component="form-footer"]:has(> :nth-child(2)) {
|
|
301
258
|
justify-content: space-between;
|
|
302
259
|
}
|
|
260
|
+
|
|
261
|
+
[data-component="logo-default"] {
|
|
262
|
+
margin: 0 auto;
|
|
263
|
+
height: 2.5rem;
|
|
264
|
+
width: auto;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
@media (prefers-color-scheme: light) {
|
|
268
|
+
[data-component="logo-default"] {
|
|
269
|
+
color: var(--color-high);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@media (prefers-color-scheme: dark) {
|
|
274
|
+
[data-component="logo-default"] {
|
|
275
|
+
color: var(--color-high);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Logo theme switching */
|
|
280
|
+
[data-component="logo"][data-mode="light"] {
|
|
281
|
+
display: none;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
[data-component="logo"][data-mode="dark"] {
|
|
285
|
+
display: block;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
@media (prefers-color-scheme: light) {
|
|
289
|
+
[data-component="logo"][data-mode="light"] {
|
|
290
|
+
display: block;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
[data-component="logo"][data-mode="dark"] {
|
|
294
|
+
display: none;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
303
297
|
`;
|
|
304
298
|
/**
|
|
305
|
-
*
|
|
306
|
-
* Handles theming, logo display, and provides consistent styling.
|
|
307
|
-
*
|
|
308
|
-
* @param props - Layout props including children and optional size
|
|
309
|
-
* @returns Complete HTML document as a string with theming and branding applied
|
|
299
|
+
* Base Layout component that provides the foundational structure for all auth UIs
|
|
310
300
|
*/
|
|
311
|
-
const Layout = (
|
|
312
|
-
const
|
|
301
|
+
const Layout = ({ children, theme, title, size }) => {
|
|
302
|
+
const currentTheme = theme || getTheme();
|
|
313
303
|
/**
|
|
314
304
|
* Gets a theme value for a specific key and color mode.
|
|
315
|
-
* Handles both string values and light/dark object configurations.
|
|
316
305
|
*/
|
|
317
306
|
const getThemeValue = (key, mode) => {
|
|
318
|
-
if (!
|
|
319
|
-
if (typeof
|
|
320
|
-
return
|
|
307
|
+
if (!currentTheme?.[key]) return;
|
|
308
|
+
if (typeof currentTheme[key] === "string") return currentTheme[key];
|
|
309
|
+
return currentTheme[key][mode];
|
|
321
310
|
};
|
|
322
311
|
/**
|
|
323
312
|
* Calculates border radius value based on theme configuration.
|
|
324
313
|
*/
|
|
325
314
|
const getBorderRadius = () => {
|
|
326
|
-
switch (
|
|
315
|
+
switch (currentTheme?.radius) {
|
|
327
316
|
case "none": return "0";
|
|
328
317
|
case "sm": return "1";
|
|
329
318
|
case "md": return "1.25";
|
|
@@ -344,11 +333,11 @@ const Layout = (props) => {
|
|
|
344
333
|
`--color-background-dark: ${getThemeValue("background", "dark") || ""}`,
|
|
345
334
|
`--color-primary-light: ${getThemeValue("primary", "light") || ""}`,
|
|
346
335
|
`--color-primary-dark: ${getThemeValue("primary", "dark") || ""}`,
|
|
347
|
-
`--font-family: ${
|
|
348
|
-
`--font-scale: ${
|
|
336
|
+
`--font-family: ${currentTheme?.font?.family || ""}`,
|
|
337
|
+
`--font-scale: ${currentTheme?.font?.scale || ""}`,
|
|
349
338
|
`--border-radius: ${getBorderRadius()}`
|
|
350
339
|
].join("; ");
|
|
351
|
-
const faviconHtml =
|
|
340
|
+
const faviconHtml = currentTheme?.favicon ? `<link href="${currentTheme.favicon}" rel="icon" />` : `
|
|
352
341
|
<link href="https://openauth.js.org/favicon.ico" rel="icon" sizes="48x48" />
|
|
353
342
|
<link href="https://openauth.js.org/favicon.svg" media="(prefers-color-scheme: light)" rel="icon" />
|
|
354
343
|
<link href="https://openauth.js.org/favicon-dark.svg" media="(prefers-color-scheme: dark)" rel="icon" />
|
|
@@ -367,56 +356,53 @@ const Layout = (props) => {
|
|
|
367
356
|
data-mode="dark"
|
|
368
357
|
src="${getThemeValue("logo", "dark") || ""}"
|
|
369
358
|
/>
|
|
370
|
-
` :
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
359
|
+
` : `
|
|
360
|
+
<svg
|
|
361
|
+
aria-label="Draft Auth Logo"
|
|
362
|
+
data-component="logo-default"
|
|
363
|
+
fill="none"
|
|
364
|
+
height="51"
|
|
365
|
+
viewBox="0 0 51 51"
|
|
366
|
+
width="51"
|
|
367
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
368
|
+
>
|
|
369
|
+
<title>Draft Auth Logo</title>
|
|
370
|
+
<path
|
|
371
|
+
d="M0 50.2303V0.12854H50.1017V50.2303H0ZM3.08002 11.8326H11.7041V3.20856H3.08002V11.8326ZM14.8526 11.8326H23.4766V3.20856H14.8526V11.8326ZM26.5566 11.8326H35.1807V3.20856H26.5566V11.8326ZM38.3292 11.8326H47.0217V3.20856H38.3292V11.8326ZM3.08002 23.6052H11.7041V14.9811H3.08002V23.6052ZM14.8526 23.6052H23.4766V14.9811H14.8526V23.6052ZM26.5566 23.6052H35.1807V14.9811H26.5566V23.6052ZM38.3292 23.6052H47.0217V14.9811H38.3292V23.6052ZM3.08002 35.3092H11.7041V26.6852H3.08002V35.3092ZM14.8526 35.3092H23.4766V26.6852H14.8526V35.3092ZM26.5566 35.3092H35.1807V26.6852H26.5566V35.3092ZM38.3292 35.3092H47.0217V26.6852H38.3292V35.3092ZM3.08002 47.1502H11.7041V38.3893H3.08002V47.1502ZM14.8526 47.1502H23.4766V38.3893H14.8526V47.1502ZM26.5566 47.1502H35.1807V38.3893H26.5566V47.1502ZM38.3292 47.1502H47.0217V38.3893H38.3292V47.1502Z"
|
|
372
|
+
fill="currentColor"
|
|
373
|
+
/>
|
|
374
|
+
</svg>
|
|
375
|
+
`;
|
|
376
|
+
return /* @__PURE__ */ jsxs("html", {
|
|
377
|
+
lang: "en",
|
|
378
|
+
style: themeStyles,
|
|
379
|
+
children: [/* @__PURE__ */ jsxs("head", { children: [
|
|
380
|
+
/* @__PURE__ */ jsx("title", { children: title || currentTheme?.title || "Draft Auth" }),
|
|
381
|
+
/* @__PURE__ */ jsx("meta", { charset: "utf-8" }),
|
|
382
|
+
/* @__PURE__ */ jsx("meta", {
|
|
383
|
+
content: "width=device-width, initial-scale=1",
|
|
384
|
+
name: "viewport"
|
|
385
|
+
}),
|
|
386
|
+
/* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: faviconHtml } }),
|
|
387
|
+
/* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: css } }),
|
|
388
|
+
currentTheme?.css && /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: currentTheme.css } })
|
|
389
|
+
] }), /* @__PURE__ */ jsx("body", { children: /* @__PURE__ */ jsx("div", {
|
|
390
|
+
"data-component": "root",
|
|
391
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
392
|
+
"data-component": "center",
|
|
393
|
+
"data-size": size || "",
|
|
394
|
+
children: [/* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: logoHtml } }), children]
|
|
395
|
+
})
|
|
396
|
+
}) })]
|
|
397
|
+
});
|
|
398
398
|
};
|
|
399
399
|
/**
|
|
400
|
-
*
|
|
401
|
-
* Used when no custom logo is provided in the theme configuration.
|
|
400
|
+
* Helper function to render a Preact component to HTML string
|
|
402
401
|
*/
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
fill="none"
|
|
408
|
-
height="51"
|
|
409
|
-
viewBox="0 0 51 51"
|
|
410
|
-
width="51"
|
|
411
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
412
|
-
>
|
|
413
|
-
<title>Draft Auth Logo</title>
|
|
414
|
-
<path
|
|
415
|
-
d="M0 50.2303V0.12854H50.1017V50.2303H0ZM3.08002 11.8326H11.7041V3.20856H3.08002V11.8326ZM14.8526 11.8326H23.4766V3.20856H14.8526V11.8326ZM26.5566 11.8326H35.1807V3.20856H26.5566V11.8326ZM38.3292 11.8326H47.0217V3.20856H38.3292V11.8326ZM3.08002 23.6052H11.7041V14.9811H3.08002V23.6052ZM14.8526 23.6052H23.4766V14.9811H14.8526V23.6052ZM26.5566 23.6052H35.1807V14.9811H26.5566V23.6052ZM38.3292 23.6052H47.0217V14.9811H38.3292V23.6052ZM3.08002 35.3092H11.7041V26.6852H3.08002V35.3092ZM14.8526 35.3092H23.4766V26.6852H14.8526V35.3092ZM26.5566 35.3092H35.1807V26.6852H26.5566V35.3092ZM38.3292 35.3092H47.0217V26.6852H38.3292V35.3092ZM3.08002 47.1502H11.7041V38.3893H3.08002V47.1502ZM14.8526 47.1502H23.4766V38.3893H14.8526V47.1502ZM26.5566 47.1502H35.1807V38.3893H26.5566V47.1502ZM38.3292 47.1502H47.0217V38.3893H38.3292V47.1502Z"
|
|
416
|
-
fill="currentColor"
|
|
417
|
-
/>
|
|
418
|
-
</svg>
|
|
419
|
-
`;
|
|
402
|
+
const renderToHTML = (component) => {
|
|
403
|
+
if (!component) return "";
|
|
404
|
+
return render(component);
|
|
405
|
+
};
|
|
420
406
|
|
|
421
407
|
//#endregion
|
|
422
|
-
export { Layout };
|
|
408
|
+
export { Layout, renderToHTML };
|