@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/ui/select.d.ts
CHANGED
|
@@ -1,233 +1,34 @@
|
|
|
1
|
+
import { Theme } from "../themes/theme.js";
|
|
2
|
+
|
|
1
3
|
//#region src/ui/select.d.ts
|
|
4
|
+
|
|
2
5
|
/**
|
|
3
|
-
*
|
|
4
|
-
* Displays a clean selection interface where users can choose their preferred authentication method.
|
|
5
|
-
*
|
|
6
|
-
* ## Features
|
|
7
|
-
*
|
|
8
|
-
* - **Multiple providers**: Support for popular OAuth providers with built-in icons
|
|
9
|
-
* - **Customizable displays**: Override provider names and copy text
|
|
10
|
-
* - **Conditional visibility**: Hide specific providers using configuration
|
|
11
|
-
* - **Type safety**: Full TypeScript support with autocomplete for known providers
|
|
12
|
-
* - **Accessibility**: Proper ARIA labels and semantic markup
|
|
13
|
-
*
|
|
14
|
-
* ## Usage
|
|
15
|
-
*
|
|
16
|
-
* ```ts
|
|
17
|
-
* import { Select } from "@draftauth/core/ui/select"
|
|
18
|
-
*
|
|
19
|
-
* export default issuer({
|
|
20
|
-
* select: Select({
|
|
21
|
-
* copy: {
|
|
22
|
-
* button_provider: "Continuar com"
|
|
23
|
-
* },
|
|
24
|
-
* displays: {
|
|
25
|
-
* code: "Código PIN",
|
|
26
|
-
* github: "Conta GitHub"
|
|
27
|
-
* },
|
|
28
|
-
* providers: {
|
|
29
|
-
* github: {
|
|
30
|
-
* hide: true
|
|
31
|
-
* },
|
|
32
|
-
* google: {
|
|
33
|
-
* display: "Google"
|
|
34
|
-
* }
|
|
35
|
-
* }
|
|
36
|
-
* })
|
|
37
|
-
* // ...
|
|
38
|
-
* })
|
|
39
|
-
* ```
|
|
40
|
-
*
|
|
41
|
-
* ## Provider Configuration
|
|
42
|
-
*
|
|
43
|
-
* Each provider can be individually configured:
|
|
44
|
-
*
|
|
45
|
-
* - **hide**: Boolean to control visibility
|
|
46
|
-
* - **display**: Custom display name override
|
|
47
|
-
*
|
|
48
|
-
* Global display overrides are applied through the `displays` property, which affects
|
|
49
|
-
* all providers of that type unless specifically overridden at the provider level.
|
|
50
|
-
*
|
|
51
|
-
* @packageDocumentation
|
|
52
|
-
*/
|
|
53
|
-
/**
|
|
54
|
-
* Default copy text used throughout the select UI.
|
|
55
|
-
* These values are used when no custom copy is provided.
|
|
56
|
-
*/
|
|
57
|
-
declare const DEFAULT_COPY: {
|
|
58
|
-
/**
|
|
59
|
-
* Copy for the provider button prefix text.
|
|
60
|
-
* @example "Continue with GitHub" where "Continue with" is this value
|
|
61
|
-
*/
|
|
62
|
-
button_provider: string;
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* Default display names for all known provider types.
|
|
66
|
-
* These provide consistent naming across the application and serve as fallbacks
|
|
67
|
-
* when no custom display name is configured.
|
|
68
|
-
*/
|
|
69
|
-
declare const DEFAULT_DISPLAY: {
|
|
70
|
-
steam: string;
|
|
71
|
-
twitch: string;
|
|
72
|
-
google: string;
|
|
73
|
-
github: string;
|
|
74
|
-
apple: string;
|
|
75
|
-
code: string;
|
|
76
|
-
x: string;
|
|
77
|
-
facebook: string;
|
|
78
|
-
microsoft: string;
|
|
79
|
-
slack: string;
|
|
80
|
-
password: string;
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* Customizable copy text for the Select UI component.
|
|
84
|
-
* Allows overriding default text to support internationalization or custom branding.
|
|
85
|
-
*/
|
|
86
|
-
type SelectCopy = typeof DEFAULT_COPY;
|
|
87
|
-
/**
|
|
88
|
-
* Union type of all known provider types that have default display names and icons.
|
|
89
|
-
* These types get autocompletion support in the displays configuration.
|
|
90
|
-
*/
|
|
91
|
-
type KnownProviderType = keyof typeof DEFAULT_DISPLAY;
|
|
92
|
-
/**
|
|
93
|
-
* Configuration options for individual providers in the select UI.
|
|
94
|
-
* Each provider can be individually controlled and customized.
|
|
6
|
+
* Provider configuration for the select UI
|
|
95
7
|
*/
|
|
96
8
|
interface ProviderConfig {
|
|
97
|
-
/**
|
|
98
|
-
* Whether to hide the provider from the select UI.
|
|
99
|
-
* When true, the provider will not appear in the selection interface.
|
|
100
|
-
*
|
|
101
|
-
* @default false
|
|
102
|
-
*/
|
|
9
|
+
/** Whether to hide the provider from the select UI */
|
|
103
10
|
hide?: boolean;
|
|
104
|
-
/**
|
|
105
|
-
* Custom display name for this specific provider instance.
|
|
106
|
-
* Overrides both the default display name and any global display override.
|
|
107
|
-
*
|
|
108
|
-
* @example "My Custom Google Login"
|
|
109
|
-
*/
|
|
11
|
+
/** Custom display name for this provider */
|
|
110
12
|
display?: string;
|
|
111
13
|
}
|
|
112
14
|
/**
|
|
113
|
-
*
|
|
114
|
-
* Provides comprehensive customization of appearance and behavior.
|
|
15
|
+
* Props for the Select component
|
|
115
16
|
*/
|
|
116
17
|
interface SelectProps {
|
|
117
|
-
/**
|
|
118
|
-
* Provider-specific configurations mapped by provider key.
|
|
119
|
-
* Each key corresponds to a provider instance, allowing individual customization.
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* ```ts
|
|
123
|
-
* {
|
|
124
|
-
* github: {
|
|
125
|
-
* hide: true
|
|
126
|
-
* },
|
|
127
|
-
* google: {
|
|
128
|
-
* display: "Google Account"
|
|
129
|
-
* },
|
|
130
|
-
* "custom-provider": {
|
|
131
|
-
* display: "Custom OAuth"
|
|
132
|
-
* }
|
|
133
|
-
* }
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
18
|
+
/** Provider-specific configurations */
|
|
136
19
|
providers?: Record<string, ProviderConfig>;
|
|
137
|
-
/**
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
* }
|
|
146
|
-
* ```
|
|
147
|
-
*/
|
|
148
|
-
copy?: Partial<SelectCopy>;
|
|
149
|
-
/**
|
|
150
|
-
* Global display name overrides for provider types.
|
|
151
|
-
*
|
|
152
|
-
* This allows you to override the default display names globally for all providers
|
|
153
|
-
* of a specific type. For known provider types, you get full autocompletion support.
|
|
154
|
-
* Custom provider types are also supported.
|
|
155
|
-
*
|
|
156
|
-
* The priority order for display names is:
|
|
157
|
-
* 1. Provider-specific `display` in `providers` config
|
|
158
|
-
* 2. Type-specific `displays` override (this property)
|
|
159
|
-
* 3. Default display name from `DEFAULT_DISPLAY`
|
|
160
|
-
* 4. Provider type string as fallback
|
|
161
|
-
*
|
|
162
|
-
* @example
|
|
163
|
-
* ```ts
|
|
164
|
-
* {
|
|
165
|
-
* displays: {
|
|
166
|
-
* code: "PIN Code", // ✅ Autocomplete available
|
|
167
|
-
* github: "GitHub Account", // ✅ Autocomplete available
|
|
168
|
-
* customType: "Custom" // ✅ Also works for unknown types
|
|
169
|
-
* }
|
|
170
|
-
* }
|
|
171
|
-
* ```
|
|
172
|
-
*/
|
|
173
|
-
displays?: Partial<Record<KnownProviderType, string>> & Record<string, string>;
|
|
20
|
+
/** Custom copy text overrides */
|
|
21
|
+
copy?: {
|
|
22
|
+
button_provider?: string;
|
|
23
|
+
};
|
|
24
|
+
/** Global display name overrides for provider types */
|
|
25
|
+
displays?: Record<string, string>;
|
|
26
|
+
/** Theme configuration */
|
|
27
|
+
theme?: Theme;
|
|
174
28
|
}
|
|
175
29
|
/**
|
|
176
|
-
* Creates a provider selection UI
|
|
177
|
-
*
|
|
178
|
-
* This component generates a complete authentication provider selection interface that:
|
|
179
|
-
* - Displays available OAuth providers as clickable buttons
|
|
180
|
-
* - Includes appropriate icons for recognized providers
|
|
181
|
-
* - Supports custom theming and internationalization
|
|
182
|
-
* - Provides accessible markup with proper ARIA attributes
|
|
183
|
-
* - Handles provider visibility and custom display names
|
|
184
|
-
*
|
|
185
|
-
* @param props - Configuration options for customizing the select UI
|
|
186
|
-
* @returns An async function that generates the HTML response for the selection interface
|
|
187
|
-
*
|
|
188
|
-
* @example
|
|
189
|
-
* ```ts
|
|
190
|
-
* // Basic usage with defaults
|
|
191
|
-
* const selectUI = Select()
|
|
192
|
-
*
|
|
193
|
-
* // Customized with provider configuration
|
|
194
|
-
* const selectUI = Select({
|
|
195
|
-
* copy: {
|
|
196
|
-
* button_provider: "Sign in with"
|
|
197
|
-
* },
|
|
198
|
-
* displays: {
|
|
199
|
-
* github: "GitHub Account",
|
|
200
|
-
* code: "Email Code"
|
|
201
|
-
* },
|
|
202
|
-
* providers: {
|
|
203
|
-
* facebook: { hide: true },
|
|
204
|
-
* google: { display: "Google Workspace" }
|
|
205
|
-
* }
|
|
206
|
-
* })
|
|
207
|
-
*
|
|
208
|
-
* // Use in issuer configuration
|
|
209
|
-
* export default issuer({
|
|
210
|
-
* select: selectUI,
|
|
211
|
-
* // ... other configuration
|
|
212
|
-
* })
|
|
213
|
-
* ```
|
|
214
|
-
*
|
|
215
|
-
* ## Provider Resolution Logic
|
|
216
|
-
*
|
|
217
|
-
* Display names are resolved in the following priority order:
|
|
218
|
-
* 1. Provider-specific `display` property
|
|
219
|
-
* 2. Global `displays` type override
|
|
220
|
-
* 3. Default display name from `DEFAULT_DISPLAY`
|
|
221
|
-
* 4. Provider type string as final fallback
|
|
222
|
-
*
|
|
223
|
-
* ## Accessibility Features
|
|
224
|
-
*
|
|
225
|
-
* The generated UI includes:
|
|
226
|
-
* - Semantic HTML structure
|
|
227
|
-
* - Proper button roles and keyboard navigation
|
|
228
|
-
* - Icon accessibility with `aria-hidden="true"`
|
|
229
|
-
* - Screen reader friendly provider names
|
|
30
|
+
* Creates a provider selection UI
|
|
230
31
|
*/
|
|
231
|
-
declare const Select: (props?: SelectProps) => (providers: Record<string, string
|
|
32
|
+
declare const Select: (props?: SelectProps) => (providers: Record<string, string>) => Promise<Response>;
|
|
232
33
|
//#endregion
|
|
233
|
-
export {
|
|
34
|
+
export { ProviderConfig, Select, SelectProps };
|
package/dist/ui/select.js
CHANGED
|
@@ -1,277 +1,90 @@
|
|
|
1
|
-
import { Layout } from "./base.js";
|
|
1
|
+
import { Layout, renderToHTML } from "./base.js";
|
|
2
2
|
import { ICON_GITHUB, ICON_GOOGLE } from "./icon.js";
|
|
3
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
3
4
|
|
|
4
|
-
//#region src/ui/select.
|
|
5
|
+
//#region src/ui/select.tsx
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
* These values are used when no custom copy is provided.
|
|
7
|
+
* Icon components for providers
|
|
8
8
|
*/
|
|
9
|
-
const
|
|
9
|
+
const PROVIDER_ICONS = {
|
|
10
|
+
github: ICON_GITHUB,
|
|
11
|
+
google: ICON_GOOGLE,
|
|
12
|
+
code: () => /* @__PURE__ */ jsx("svg", {
|
|
13
|
+
width: "20",
|
|
14
|
+
height: "20",
|
|
15
|
+
viewBox: "0 0 52 52",
|
|
16
|
+
fill: "currentColor",
|
|
17
|
+
"aria-label": "Code authentication",
|
|
18
|
+
role: "img",
|
|
19
|
+
children: /* @__PURE__ */ jsx("path", { d: "M8.55,36.91A6.55,6.55,0,1,1,2,43.45,6.54,6.54,0,0,1,8.55,36.91Zm17.45,0a6.55,6.55,0,1,1-6.55,6.54A6.55,6.55,0,0,1,26,36.91Zm17.45,0a6.55,6.55,0,1,1-6.54,6.54A6.54,6.54,0,0,1,43.45,36.91ZM8.55,19.45A6.55,6.55,0,1,1,2,26,6.55,6.55,0,0,1,8.55,19.45Zm17.45,0A6.55,6.55,0,1,1,19.45,26,6.56,6.56,0,0,1,26,19.45Zm17.45,0A6.55,6.55,0,1,1,36.91,26,6.55,6.55,0,0,1,43.45,19.45ZM8.55,2A6.55,6.55,0,1,1,2,8.55,6.54,6.54,0,0,1,8.55,2ZM26,2a6.55,6.55,0,1,1-6.55,6.55A6.55,6.55,0,0,1,26,2ZM43.45,2a6.55,6.55,0,1,1-6.54,6.55A6.55,6.55,0,0,1,43.45,2Z" })
|
|
20
|
+
})
|
|
21
|
+
};
|
|
10
22
|
/**
|
|
11
|
-
* Default display names for
|
|
12
|
-
* These provide consistent naming across the application and serve as fallbacks
|
|
13
|
-
* when no custom display name is configured.
|
|
23
|
+
* Default display names for provider types
|
|
14
24
|
*/
|
|
15
|
-
const
|
|
16
|
-
steam: "Steam",
|
|
17
|
-
twitch: "Twitch",
|
|
18
|
-
google: "Google",
|
|
25
|
+
const DEFAULT_DISPLAYS = {
|
|
19
26
|
github: "GitHub",
|
|
20
|
-
|
|
27
|
+
google: "Google",
|
|
21
28
|
code: "Code",
|
|
22
|
-
x: "X",
|
|
23
|
-
facebook: "Facebook",
|
|
24
|
-
microsoft: "Microsoft",
|
|
25
|
-
slack: "Slack",
|
|
26
29
|
password: "Password"
|
|
27
30
|
};
|
|
28
31
|
/**
|
|
29
|
-
*
|
|
30
|
-
* Each icon is an optimized SVG component with proper accessibility attributes.
|
|
31
|
-
*
|
|
32
|
-
* Icons are designed to:
|
|
33
|
-
* - Scale properly at different sizes
|
|
34
|
-
* - Inherit text color for theming
|
|
35
|
-
* - Include proper ARIA attributes
|
|
36
|
-
* - Work with screen readers
|
|
32
|
+
* Individual provider button component
|
|
37
33
|
*/
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
twitch: `
|
|
82
|
-
<svg
|
|
83
|
-
aria-hidden="true"
|
|
84
|
-
role="img"
|
|
85
|
-
viewBox="0 0 448 512"
|
|
86
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
87
|
-
>
|
|
88
|
-
<path
|
|
89
|
-
d="M40.1 32L10 108.9v314.3h107V480h60.2l56.8-56.8h87l117-117V32H40.1zm357.8 254.1L331 353H224l-56.8 56.8V353H76.9V72.1h321v214zM331 149v116.9h-40.1V149H331zm-107 0v116.9h-40.1V149H224z"
|
|
90
|
-
fill="currentColor"
|
|
91
|
-
/>
|
|
92
|
-
</svg>
|
|
93
|
-
`,
|
|
94
|
-
google: ICON_GOOGLE,
|
|
95
|
-
github: ICON_GITHUB,
|
|
96
|
-
apple: `
|
|
97
|
-
<svg
|
|
98
|
-
aria-hidden="true"
|
|
99
|
-
role="img"
|
|
100
|
-
viewBox="0 0 814 1000"
|
|
101
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
102
|
-
>
|
|
103
|
-
<path
|
|
104
|
-
d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z "
|
|
105
|
-
fill="currentColor"
|
|
106
|
-
/>
|
|
107
|
-
</svg>
|
|
108
|
-
`,
|
|
109
|
-
x: `
|
|
110
|
-
<svg
|
|
111
|
-
aria-hidden="true"
|
|
112
|
-
role="img"
|
|
113
|
-
viewBox="0 0 1200 1227"
|
|
114
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
115
|
-
>
|
|
116
|
-
<path
|
|
117
|
-
d="M714.163 519.284 1160.89 0h-105.86L667.137 450.887 357.328 0H0l468.492 681.821L0 1226.37h105.866l409.625-476.152 327.181 476.152H1200L714.137 519.284h.026ZM569.165 687.828l-47.468-67.894-377.686-540.24h162.604l304.797 435.991 47.468 67.894 396.2 566.721H892.476L569.165 687.854v-.026Z"
|
|
118
|
-
fill="currentColor"
|
|
119
|
-
/>
|
|
120
|
-
</svg>
|
|
121
|
-
`,
|
|
122
|
-
microsoft: `
|
|
123
|
-
<svg
|
|
124
|
-
aria-hidden="true"
|
|
125
|
-
preserveAspectRatio="xMidYMid"
|
|
126
|
-
role="img"
|
|
127
|
-
viewBox="0 0 256 256"
|
|
128
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
129
|
-
>
|
|
130
|
-
<path d="M121.666 121.666H0V0h121.666z" fill="#F1511B" />
|
|
131
|
-
<path d="M256 121.666H134.335V0H256z" fill="#80CC28" />
|
|
132
|
-
<path d="M121.663 256.002H0V134.336h121.663z" fill="#00ADEF" />
|
|
133
|
-
<path d="M256 256.002H134.335V134.336H256z" fill="#FBBC09" />
|
|
134
|
-
</svg>
|
|
135
|
-
`,
|
|
136
|
-
facebook: `
|
|
137
|
-
<svg
|
|
138
|
-
aria-hidden="true"
|
|
139
|
-
fill="url(#a)"
|
|
140
|
-
role="img"
|
|
141
|
-
viewBox="0 0 36 36"
|
|
142
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
143
|
-
>
|
|
144
|
-
<defs>
|
|
145
|
-
<linearGradient id="a" x1="50%" x2="50%" y1="97.078%" y2="0%">
|
|
146
|
-
<stop offset="0%" stop-color="#0062E0" />
|
|
147
|
-
<stop offset="100%" stop-color="#19AFFF" />
|
|
148
|
-
</linearGradient>
|
|
149
|
-
</defs>
|
|
150
|
-
<path d="M15 35.8C6.5 34.3 0 26.9 0 18 0 8.1 8.1 0 18 0s18 8.1 18 18c0 8.9-6.5 16.3-15 17.8l-1-.8h-4l-1 .8z" />
|
|
151
|
-
<path
|
|
152
|
-
d="m25 23 .8-5H21v-3.5c0-1.4.5-2.5 2.7-2.5H26V7.4c-1.3-.2-2.7-.4-4-.4-4.1 0-7 2.5-7 7v4h-4.5v5H15v12.7c1 .2 2 .3 3 .3s2-.1 3-.3V23h4z"
|
|
153
|
-
fill="#FFF"
|
|
154
|
-
/>
|
|
155
|
-
</svg>
|
|
156
|
-
`,
|
|
157
|
-
slack: `
|
|
158
|
-
<svg
|
|
159
|
-
aria-hidden="true"
|
|
160
|
-
enable-background="new 0 0 2447.6 2452.5"
|
|
161
|
-
role="img"
|
|
162
|
-
viewBox="0 0 2447.6 2452.5"
|
|
163
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
164
|
-
>
|
|
165
|
-
<g clip-rule="evenodd" fill-rule="evenodd">
|
|
166
|
-
<path
|
|
167
|
-
d="m897.4 0c-135.3.1-244.8 109.9-244.7 245.2-.1 135.3 109.5 245.1 244.8 245.2h244.8v-245.1c.1-135.3-109.5-245.1-244.9-245.3.1 0 .1 0 0 0m0 654h-652.6c-135.3.1-244.9 109.9-244.8 245.2-.2 135.3 109.4 245.1 244.7 245.3h652.7c135.3-.1 244.9-109.9 244.8-245.2.1-135.4-109.5-245.2-244.8-245.3z"
|
|
168
|
-
fill="#36c5f0"
|
|
169
|
-
/>
|
|
170
|
-
<path
|
|
171
|
-
d="m2447.6 899.2c.1-135.3-109.5-245.1-244.8-245.2-135.3.1-244.9 109.9-244.8 245.2v245.3h244.8c135.3-.1 244.9-109.9 244.8-245.3zm-652.7 0v-654c.1-135.2-109.4-245-244.7-245.2-135.3.1-244.9 109.9-244.8 245.2v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.3z"
|
|
172
|
-
fill="#2eb67d"
|
|
173
|
-
/>
|
|
174
|
-
<path
|
|
175
|
-
d="m1550.1 2452.5c135.3-.1 244.9-109.9 244.8-245.2.1-135.3-109.5-245.1-244.8-245.2h-244.8v245.2c-.1 135.2 109.5 245 244.8 245.2zm0-654.1h652.7c135.3-.1 244.9-109.9 244.8-245.2.2-135.3-109.4-245.1-244.7-245.3h-652.7c-135.3.1-244.9 109.9-244.8 245.2-.1 135.4 109.4 245.2 244.7 245.3z"
|
|
176
|
-
fill="#ecb22e"
|
|
177
|
-
/>
|
|
178
|
-
<path
|
|
179
|
-
d="m0 1553.2c-.1 135.3 109.5 245.1 244.8 245.2 135.3-.1 244.9-109.9 244.8-245.2v-245.2h-244.8c-135.3.1-244.9 109.9-244.8 245.2zm652.7 0v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.2v-653.9c.2-135.3-109.4-245.1-244.7-245.3-135.4 0-244.9 109.8-244.8 245.1 0 0 0 .1 0 0"
|
|
180
|
-
fill="#e01e5a"
|
|
181
|
-
/>
|
|
182
|
-
</g>
|
|
183
|
-
</svg>
|
|
184
|
-
`
|
|
34
|
+
const ProviderButton = ({ providerKey, providerType, config, displays, buttonText }) => {
|
|
35
|
+
const displayName = config?.display || displays[providerType] || DEFAULT_DISPLAYS[providerType] || providerType;
|
|
36
|
+
const IconComponent = PROVIDER_ICONS[providerKey] || PROVIDER_ICONS[providerType];
|
|
37
|
+
return /* @__PURE__ */ jsxs("a", {
|
|
38
|
+
href: `./${providerKey}/authorize`,
|
|
39
|
+
"data-component": "button",
|
|
40
|
+
"data-color": "ghost",
|
|
41
|
+
"aria-label": `${buttonText} ${displayName}`,
|
|
42
|
+
children: [
|
|
43
|
+
IconComponent && /* @__PURE__ */ jsx("i", {
|
|
44
|
+
"data-slot": "icon",
|
|
45
|
+
children: /* @__PURE__ */ jsx(IconComponent, {})
|
|
46
|
+
}),
|
|
47
|
+
buttonText,
|
|
48
|
+
" ",
|
|
49
|
+
displayName
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Main provider selection component
|
|
55
|
+
*/
|
|
56
|
+
const ProviderSelect = ({ providers, config = {}, theme }) => {
|
|
57
|
+
const buttonText = config.copy?.button_provider || "Continue with";
|
|
58
|
+
const displays = {
|
|
59
|
+
...DEFAULT_DISPLAYS,
|
|
60
|
+
...config.displays
|
|
61
|
+
};
|
|
62
|
+
const visibleProviders = Object.entries(providers).filter(([key]) => !config.providers?.[key]?.hide);
|
|
63
|
+
return /* @__PURE__ */ jsx(Layout, {
|
|
64
|
+
theme,
|
|
65
|
+
title: "Sign In",
|
|
66
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
67
|
+
"data-component": "form",
|
|
68
|
+
children: visibleProviders.map(([key, type]) => /* @__PURE__ */ jsx(ProviderButton, {
|
|
69
|
+
providerKey: key,
|
|
70
|
+
providerType: type,
|
|
71
|
+
config: config.providers?.[key],
|
|
72
|
+
displays,
|
|
73
|
+
buttonText
|
|
74
|
+
}, key))
|
|
75
|
+
})
|
|
76
|
+
});
|
|
185
77
|
};
|
|
186
78
|
/**
|
|
187
|
-
* Creates a provider selection UI
|
|
188
|
-
*
|
|
189
|
-
* This component generates a complete authentication provider selection interface that:
|
|
190
|
-
* - Displays available OAuth providers as clickable buttons
|
|
191
|
-
* - Includes appropriate icons for recognized providers
|
|
192
|
-
* - Supports custom theming and internationalization
|
|
193
|
-
* - Provides accessible markup with proper ARIA attributes
|
|
194
|
-
* - Handles provider visibility and custom display names
|
|
195
|
-
*
|
|
196
|
-
* @param props - Configuration options for customizing the select UI
|
|
197
|
-
* @returns An async function that generates the HTML response for the selection interface
|
|
198
|
-
*
|
|
199
|
-
* @example
|
|
200
|
-
* ```ts
|
|
201
|
-
* // Basic usage with defaults
|
|
202
|
-
* const selectUI = Select()
|
|
203
|
-
*
|
|
204
|
-
* // Customized with provider configuration
|
|
205
|
-
* const selectUI = Select({
|
|
206
|
-
* copy: {
|
|
207
|
-
* button_provider: "Sign in with"
|
|
208
|
-
* },
|
|
209
|
-
* displays: {
|
|
210
|
-
* github: "GitHub Account",
|
|
211
|
-
* code: "Email Code"
|
|
212
|
-
* },
|
|
213
|
-
* providers: {
|
|
214
|
-
* facebook: { hide: true },
|
|
215
|
-
* google: { display: "Google Workspace" }
|
|
216
|
-
* }
|
|
217
|
-
* })
|
|
218
|
-
*
|
|
219
|
-
* // Use in issuer configuration
|
|
220
|
-
* export default issuer({
|
|
221
|
-
* select: selectUI,
|
|
222
|
-
* // ... other configuration
|
|
223
|
-
* })
|
|
224
|
-
* ```
|
|
225
|
-
*
|
|
226
|
-
* ## Provider Resolution Logic
|
|
227
|
-
*
|
|
228
|
-
* Display names are resolved in the following priority order:
|
|
229
|
-
* 1. Provider-specific `display` property
|
|
230
|
-
* 2. Global `displays` type override
|
|
231
|
-
* 3. Default display name from `DEFAULT_DISPLAY`
|
|
232
|
-
* 4. Provider type string as final fallback
|
|
233
|
-
*
|
|
234
|
-
* ## Accessibility Features
|
|
235
|
-
*
|
|
236
|
-
* The generated UI includes:
|
|
237
|
-
* - Semantic HTML structure
|
|
238
|
-
* - Proper button roles and keyboard navigation
|
|
239
|
-
* - Icon accessibility with `aria-hidden="true"`
|
|
240
|
-
* - Screen reader friendly provider names
|
|
79
|
+
* Creates a provider selection UI
|
|
241
80
|
*/
|
|
242
|
-
const Select = (props) => {
|
|
243
|
-
return async (providers
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
...DEFAULT_DISPLAY,
|
|
250
|
-
...props?.displays
|
|
251
|
-
};
|
|
252
|
-
const providerButtons = Object.entries(providers).map(([providerKey, providerType]) => {
|
|
253
|
-
const providerConfig = props?.providers?.[providerKey];
|
|
254
|
-
if (providerConfig?.hide) return "";
|
|
255
|
-
const displayName = providerConfig?.display || displays[providerType] || providerType;
|
|
256
|
-
const icon = ICON[providerKey];
|
|
257
|
-
return `
|
|
258
|
-
<a
|
|
259
|
-
aria-label="${copy.button_provider} ${displayName}"
|
|
260
|
-
data-color="ghost"
|
|
261
|
-
data-component="button"
|
|
262
|
-
href="./${providerKey}/authorize"
|
|
263
|
-
>
|
|
264
|
-
${icon ? `<i data-slot="icon">${icon}</i>` : ""}
|
|
265
|
-
${copy.button_provider} ${displayName}
|
|
266
|
-
</a>
|
|
267
|
-
`;
|
|
268
|
-
}).filter((button) => button !== "").join("");
|
|
269
|
-
const formContent = `
|
|
270
|
-
<div data-component="form">
|
|
271
|
-
${providerButtons}
|
|
272
|
-
</div>
|
|
273
|
-
`;
|
|
274
|
-
const html = Layout({ children: formContent });
|
|
81
|
+
const Select = (props = {}) => {
|
|
82
|
+
return async (providers) => {
|
|
83
|
+
const html = renderToHTML(/* @__PURE__ */ jsx(ProviderSelect, {
|
|
84
|
+
providers,
|
|
85
|
+
config: props,
|
|
86
|
+
theme: props.theme
|
|
87
|
+
}));
|
|
275
88
|
return new Response(html, { headers: { "Content-Type": "text/html" } });
|
|
276
89
|
};
|
|
277
90
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@draftlab/auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core implementation for @draftlab/auth",
|
|
6
6
|
"author": "Matheus Pergoli",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
],
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@types/node": "^24.0.
|
|
40
|
+
"@types/node": "^24.0.13",
|
|
41
41
|
"tsdown": "^0.12.9",
|
|
42
42
|
"typescript": "^5.8.3",
|
|
43
43
|
"@draftlab/tsconfig": "0.1.0"
|
|
@@ -57,6 +57,8 @@
|
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@standard-schema/spec": "^1.0.0",
|
|
59
59
|
"jose": "^6.0.11",
|
|
60
|
+
"preact": "^10.26.9",
|
|
61
|
+
"preact-render-to-string": "^6.5.13",
|
|
60
62
|
"@draftlab/auth-router": "0.0.2"
|
|
61
63
|
},
|
|
62
64
|
"engines": {
|