@draftlab/auth 0.5.0 → 0.7.0
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/client.d.mts +45 -2
- package/dist/client.mjs +26 -0
- package/dist/core.mjs +32 -1
- package/dist/provider/apple.d.mts +105 -0
- package/dist/provider/apple.mjs +151 -0
- package/dist/provider/gitlab.d.mts +100 -0
- package/dist/provider/gitlab.mjs +128 -0
- package/dist/provider/reddit.d.mts +101 -0
- package/dist/provider/reddit.mjs +114 -0
- package/dist/provider/slack.d.mts +108 -0
- package/dist/provider/slack.mjs +125 -0
- package/dist/provider/spotify.d.mts +107 -0
- package/dist/provider/spotify.mjs +122 -0
- package/dist/provider/twitch.d.mts +102 -0
- package/dist/provider/twitch.mjs +118 -0
- package/dist/revocation.d.mts +55 -0
- package/dist/revocation.mjs +63 -0
- package/dist/ui/icon.d.mts +41 -4
- package/dist/ui/icon.mjs +196 -19
- package/dist/ui/select.mjs +27 -4
- package/package.json +1 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Provider } from "./provider.mjs";
|
|
2
|
+
import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/provider/twitch.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration options for Twitch OAuth 2.0 provider.
|
|
8
|
+
* Extends the base OAuth 2.0 configuration with Twitch-specific documentation.
|
|
9
|
+
*/
|
|
10
|
+
interface TwitchConfig extends Oauth2WrappedConfig {
|
|
11
|
+
/**
|
|
12
|
+
* Twitch application client ID.
|
|
13
|
+
* Get this from your Twitch Console at https://dev.twitch.tv/console
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* {
|
|
18
|
+
* clientID: "abcdef123456"
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
readonly clientID: string;
|
|
23
|
+
/**
|
|
24
|
+
* Twitch application client secret.
|
|
25
|
+
* Keep this secure and never expose it to client-side code.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* {
|
|
30
|
+
* clientSecret: process.env.TWITCH_CLIENT_SECRET
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
readonly clientSecret: string;
|
|
35
|
+
/**
|
|
36
|
+
* Twitch OAuth scopes to request access for.
|
|
37
|
+
* Determines what data and actions your app can access.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* {
|
|
42
|
+
* scopes: [
|
|
43
|
+
* "user:read:email", // Access user email
|
|
44
|
+
* "user:read:subscriptions" // View subscriptions
|
|
45
|
+
* ]
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
readonly scopes: string[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Creates a Twitch OAuth 2.0 authentication provider.
|
|
53
|
+
* Allows users to authenticate using their Twitch accounts.
|
|
54
|
+
*
|
|
55
|
+
* @param config - Twitch OAuth 2.0 configuration
|
|
56
|
+
* @returns OAuth 2.0 provider configured for Twitch
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* // Basic Twitch authentication
|
|
61
|
+
* const basicTwitch = TwitchProvider({
|
|
62
|
+
* clientID: process.env.TWITCH_CLIENT_ID,
|
|
63
|
+
* clientSecret: process.env.TWITCH_CLIENT_SECRET
|
|
64
|
+
* })
|
|
65
|
+
*
|
|
66
|
+
* // Twitch with email scope
|
|
67
|
+
* const twitchWithEmail = TwitchProvider({
|
|
68
|
+
* clientID: process.env.TWITCH_CLIENT_ID,
|
|
69
|
+
* clientSecret: process.env.TWITCH_CLIENT_SECRET,
|
|
70
|
+
* scopes: ["user:read:email"]
|
|
71
|
+
* })
|
|
72
|
+
*
|
|
73
|
+
* // Using the access token to fetch user data
|
|
74
|
+
* export default issuer({
|
|
75
|
+
* providers: { twitch: twitchWithEmail },
|
|
76
|
+
* success: async (ctx, value) => {
|
|
77
|
+
* if (value.provider === "twitch") {
|
|
78
|
+
* const token = value.tokenset.access
|
|
79
|
+
*
|
|
80
|
+
* const userRes = await fetch('https://api.twitch.tv/helix/users', {
|
|
81
|
+
* headers: {
|
|
82
|
+
* 'Authorization': `Bearer ${token}`,
|
|
83
|
+
* 'Client-ID': process.env.TWITCH_CLIENT_ID
|
|
84
|
+
* }
|
|
85
|
+
* })
|
|
86
|
+
* const { data } = await userRes.json()
|
|
87
|
+
* const user = data[0]
|
|
88
|
+
*
|
|
89
|
+
* return ctx.subject("user", {
|
|
90
|
+
* twitchId: user.id,
|
|
91
|
+
* login: user.login,
|
|
92
|
+
* email: user.email,
|
|
93
|
+
* displayName: user.display_name
|
|
94
|
+
* })
|
|
95
|
+
* }
|
|
96
|
+
* }
|
|
97
|
+
* })
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
declare const TwitchProvider: (config: TwitchConfig) => Provider<Oauth2UserData>;
|
|
101
|
+
//#endregion
|
|
102
|
+
export { TwitchConfig, TwitchProvider };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Oauth2Provider } from "./oauth2.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/provider/twitch.ts
|
|
4
|
+
/**
|
|
5
|
+
* Twitch authentication provider for Draft Auth.
|
|
6
|
+
* Implements OAuth 2.0 flow for authenticating users with their Twitch accounts.
|
|
7
|
+
*
|
|
8
|
+
* ## Quick Setup
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { TwitchProvider } from "@draftlab/auth/provider/twitch"
|
|
12
|
+
*
|
|
13
|
+
* export default issuer({
|
|
14
|
+
* providers: {
|
|
15
|
+
* twitch: TwitchProvider({
|
|
16
|
+
* clientID: process.env.TWITCH_CLIENT_ID,
|
|
17
|
+
* clientSecret: process.env.TWITCH_CLIENT_SECRET,
|
|
18
|
+
* scopes: ["user:read:email"]
|
|
19
|
+
* })
|
|
20
|
+
* }
|
|
21
|
+
* })
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ## Common Scopes
|
|
25
|
+
*
|
|
26
|
+
* - `user:read:email` - Access user's email address
|
|
27
|
+
* - `user:read:subscriptions` - View user subscriptions
|
|
28
|
+
* - `user:read:follows` - View user's follows
|
|
29
|
+
* - `channel:read:subscriptions` - View channel subscribers
|
|
30
|
+
* - `analytics:read:games` - View game analytics
|
|
31
|
+
* - `bits:read` - View bits information
|
|
32
|
+
*
|
|
33
|
+
* ## User Data Access
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* success: async (ctx, value) => {
|
|
37
|
+
* if (value.provider === "twitch") {
|
|
38
|
+
* const accessToken = value.tokenset.access
|
|
39
|
+
*
|
|
40
|
+
* // Fetch user information
|
|
41
|
+
* const userResponse = await fetch('https://api.twitch.tv/helix/users', {
|
|
42
|
+
* headers: {
|
|
43
|
+
* 'Authorization': `Bearer ${accessToken}`,
|
|
44
|
+
* 'Client-ID': process.env.TWITCH_CLIENT_ID
|
|
45
|
+
* }
|
|
46
|
+
* })
|
|
47
|
+
* const { data } = await userResponse.json()
|
|
48
|
+
* const user = data[0]
|
|
49
|
+
*
|
|
50
|
+
* // User info available: id, login, display_name, email, profile_image_url
|
|
51
|
+
* }
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @packageDocumentation
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* Creates a Twitch OAuth 2.0 authentication provider.
|
|
59
|
+
* Allows users to authenticate using their Twitch accounts.
|
|
60
|
+
*
|
|
61
|
+
* @param config - Twitch OAuth 2.0 configuration
|
|
62
|
+
* @returns OAuth 2.0 provider configured for Twitch
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* // Basic Twitch authentication
|
|
67
|
+
* const basicTwitch = TwitchProvider({
|
|
68
|
+
* clientID: process.env.TWITCH_CLIENT_ID,
|
|
69
|
+
* clientSecret: process.env.TWITCH_CLIENT_SECRET
|
|
70
|
+
* })
|
|
71
|
+
*
|
|
72
|
+
* // Twitch with email scope
|
|
73
|
+
* const twitchWithEmail = TwitchProvider({
|
|
74
|
+
* clientID: process.env.TWITCH_CLIENT_ID,
|
|
75
|
+
* clientSecret: process.env.TWITCH_CLIENT_SECRET,
|
|
76
|
+
* scopes: ["user:read:email"]
|
|
77
|
+
* })
|
|
78
|
+
*
|
|
79
|
+
* // Using the access token to fetch user data
|
|
80
|
+
* export default issuer({
|
|
81
|
+
* providers: { twitch: twitchWithEmail },
|
|
82
|
+
* success: async (ctx, value) => {
|
|
83
|
+
* if (value.provider === "twitch") {
|
|
84
|
+
* const token = value.tokenset.access
|
|
85
|
+
*
|
|
86
|
+
* const userRes = await fetch('https://api.twitch.tv/helix/users', {
|
|
87
|
+
* headers: {
|
|
88
|
+
* 'Authorization': `Bearer ${token}`,
|
|
89
|
+
* 'Client-ID': process.env.TWITCH_CLIENT_ID
|
|
90
|
+
* }
|
|
91
|
+
* })
|
|
92
|
+
* const { data } = await userRes.json()
|
|
93
|
+
* const user = data[0]
|
|
94
|
+
*
|
|
95
|
+
* return ctx.subject("user", {
|
|
96
|
+
* twitchId: user.id,
|
|
97
|
+
* login: user.login,
|
|
98
|
+
* email: user.email,
|
|
99
|
+
* displayName: user.display_name
|
|
100
|
+
* })
|
|
101
|
+
* }
|
|
102
|
+
* }
|
|
103
|
+
* })
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
const TwitchProvider = (config) => {
|
|
107
|
+
return Oauth2Provider({
|
|
108
|
+
...config,
|
|
109
|
+
type: "twitch",
|
|
110
|
+
endpoint: {
|
|
111
|
+
authorization: "https://id.twitch.tv/oauth2/authorize",
|
|
112
|
+
token: "https://id.twitch.tv/oauth2/token"
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
//#endregion
|
|
118
|
+
export { TwitchProvider };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { StorageAdapter } from "./storage/storage.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/revocation.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Data stored for a revoked token.
|
|
7
|
+
* Tracks when the token was revoked and when it naturally expires.
|
|
8
|
+
*/
|
|
9
|
+
interface RevocationRecord {
|
|
10
|
+
/** Timestamp when the token was revoked (milliseconds) */
|
|
11
|
+
revokedAt: number;
|
|
12
|
+
/** Timestamp when the token naturally expires (milliseconds) */
|
|
13
|
+
expiresAt: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Token revocation manager.
|
|
17
|
+
* Provides methods to revoke tokens and check if a token has been revoked.
|
|
18
|
+
*/
|
|
19
|
+
declare const Revocation: {
|
|
20
|
+
/**
|
|
21
|
+
* Revokes a token, preventing it from being used even if not yet expired.
|
|
22
|
+
*
|
|
23
|
+
* @param storage - Storage adapter to use
|
|
24
|
+
* @param token - The token to revoke (access or refresh token)
|
|
25
|
+
* @param expiresAt - When the token naturally expires (milliseconds since epoch)
|
|
26
|
+
* @returns Promise that resolves when revocation is stored
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* // Revoke a refresh token on logout
|
|
31
|
+
* await Revocation.revoke(storage, refreshToken, expiresAt)
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
readonly revoke: (storage: StorageAdapter, token: string, expiresAt: number) => Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Checks if a token has been revoked.
|
|
37
|
+
* Returns false if token is not in revocation list (never revoked or already expired).
|
|
38
|
+
*
|
|
39
|
+
* @param storage - Storage adapter to use
|
|
40
|
+
* @param token - The token to check
|
|
41
|
+
* @returns Promise resolving to true if token is revoked, false otherwise
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* // Check if token was revoked before using it
|
|
46
|
+
* const isRevoked = await Revocation.isRevoked(storage, accessToken)
|
|
47
|
+
* if (isRevoked) {
|
|
48
|
+
* throw new InvalidAccessTokenError()
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
readonly isRevoked: (storage: StorageAdapter, token: string) => Promise<boolean>;
|
|
53
|
+
};
|
|
54
|
+
//#endregion
|
|
55
|
+
export { Revocation, RevocationRecord };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Storage } from "./storage/storage.mjs";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
|
|
4
|
+
//#region src/revocation.ts
|
|
5
|
+
/**
|
|
6
|
+
* Token revocation management for Draft Auth.
|
|
7
|
+
* Handles blacklisting of revoked tokens to prevent their use.
|
|
8
|
+
*
|
|
9
|
+
* ## Overview
|
|
10
|
+
*
|
|
11
|
+
* Revocation allows users to invalidate specific tokens before their natural expiration.
|
|
12
|
+
* This is essential for logout functionality and security in case of token compromise.
|
|
13
|
+
*
|
|
14
|
+
* ## Storage Structure
|
|
15
|
+
*
|
|
16
|
+
* Revoked tokens are stored with their expiration time to allow automatic cleanup:
|
|
17
|
+
* ```
|
|
18
|
+
* revocation:token:{tokenHash} → { revokedAt: timestamp, expiresAt: timestamp }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* ## Security Considerations
|
|
22
|
+
*
|
|
23
|
+
* - Revoked tokens are checked on every use
|
|
24
|
+
* - Storage automatically cleans up expired revocations
|
|
25
|
+
* - Hash tokens for storage to reduce memory usage
|
|
26
|
+
* - Use constant-time comparison for hash verification
|
|
27
|
+
*
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Hashes a token for storage.
|
|
32
|
+
* Uses SHA-256 to reduce storage size and prevent exposure of full token value.
|
|
33
|
+
*
|
|
34
|
+
* @param token - The token to hash
|
|
35
|
+
* @returns SHA-256 hash of the token
|
|
36
|
+
*
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
const hashToken = (token) => {
|
|
40
|
+
return createHash("sha256").update(token).digest("hex");
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Token revocation manager.
|
|
44
|
+
* Provides methods to revoke tokens and check if a token has been revoked.
|
|
45
|
+
*/
|
|
46
|
+
const Revocation = {
|
|
47
|
+
revoke: async (storage, token, expiresAt) => {
|
|
48
|
+
const key = ["revocation:token", hashToken(token)];
|
|
49
|
+
const record = {
|
|
50
|
+
revokedAt: Date.now(),
|
|
51
|
+
expiresAt
|
|
52
|
+
};
|
|
53
|
+
const ttlSeconds = Math.ceil((expiresAt - Date.now()) / 1e3);
|
|
54
|
+
await Storage.set(storage, key, record, Math.max(1, ttlSeconds));
|
|
55
|
+
},
|
|
56
|
+
isRevoked: async (storage, token) => {
|
|
57
|
+
const key = ["revocation:token", hashToken(token)];
|
|
58
|
+
return !!await Storage.get(storage, key);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { Revocation };
|
package/dist/ui/icon.d.mts
CHANGED
|
@@ -4,18 +4,55 @@ import { ComponentChildren } from "preact";
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* GitHub brand icon with official logo design.
|
|
7
|
-
* Used for GitHub authentication provider buttons and references.
|
|
8
7
|
*/
|
|
9
8
|
declare const ICON_GITHUB: () => ComponentChildren;
|
|
10
9
|
/**
|
|
11
10
|
* Google brand icon with official multicolor logo design.
|
|
12
|
-
* Used for Google authentication provider buttons and references.
|
|
13
11
|
*/
|
|
14
12
|
declare const ICON_GOOGLE: () => ComponentChildren;
|
|
15
13
|
/**
|
|
16
14
|
* Email envelope icon for email-related authentication flows.
|
|
17
|
-
* Used in email verification, password reset, and contact forms.
|
|
18
15
|
*/
|
|
19
16
|
declare const ICON_EMAIL: () => ComponentChildren;
|
|
17
|
+
/**
|
|
18
|
+
* Apple brand icon for Sign in with Apple.
|
|
19
|
+
*/
|
|
20
|
+
declare const ICON_APPLE: () => ComponentChildren;
|
|
21
|
+
/**
|
|
22
|
+
* Discord brand icon.
|
|
23
|
+
*/
|
|
24
|
+
declare const ICON_DISCORD: () => ComponentChildren;
|
|
25
|
+
/**
|
|
26
|
+
* Facebook brand icon with gradient.
|
|
27
|
+
*/
|
|
28
|
+
declare const ICON_FACEBOOK: () => ComponentChildren;
|
|
29
|
+
/**
|
|
30
|
+
* LinkedIn brand icon.
|
|
31
|
+
*/
|
|
32
|
+
declare const ICON_LINKEDIN: () => ComponentChildren;
|
|
33
|
+
/**
|
|
34
|
+
* Microsoft brand icon with four color squares.
|
|
35
|
+
*/
|
|
36
|
+
declare const ICON_MICROSOFT: () => ComponentChildren;
|
|
37
|
+
/**
|
|
38
|
+
* Slack brand icon.
|
|
39
|
+
*/
|
|
40
|
+
declare const ICON_SLACK: () => ComponentChildren;
|
|
41
|
+
/**
|
|
42
|
+
* GitLab brand icon.
|
|
43
|
+
*/
|
|
44
|
+
declare const ICON_GITLAB: () => ComponentChildren;
|
|
45
|
+
/**
|
|
46
|
+
* Reddit brand icon.
|
|
47
|
+
*/
|
|
48
|
+
declare const ICON_REDDIT: () => ComponentChildren;
|
|
49
|
+
/**
|
|
50
|
+
* Spotify brand icon.
|
|
51
|
+
*/
|
|
52
|
+
declare const ICON_SPOTIFY: () => ComponentChildren;
|
|
53
|
+
/**
|
|
54
|
+
* Twitch brand icon.
|
|
55
|
+
*/
|
|
56
|
+
declare const ICON_TWITCH: () => ComponentChildren;
|
|
20
57
|
//#endregion
|
|
21
|
-
export { ICON_EMAIL, ICON_GITHUB, ICON_GOOGLE };
|
|
58
|
+
export { ICON_APPLE, ICON_DISCORD, ICON_EMAIL, ICON_FACEBOOK, ICON_GITHUB, ICON_GITLAB, ICON_GOOGLE, ICON_LINKEDIN, ICON_MICROSOFT, ICON_REDDIT, ICON_SLACK, ICON_SPOTIFY, ICON_TWITCH };
|
package/dist/ui/icon.mjs
CHANGED
|
@@ -3,31 +3,29 @@ import { jsx, jsxs } from "preact/jsx-runtime";
|
|
|
3
3
|
//#region src/ui/icon.tsx
|
|
4
4
|
/**
|
|
5
5
|
* GitHub brand icon with official logo design.
|
|
6
|
-
* Used for GitHub authentication provider buttons and references.
|
|
7
6
|
*/
|
|
8
7
|
const ICON_GITHUB = () => /* @__PURE__ */ jsx("svg", {
|
|
9
|
-
"aria-label": "GitHub",
|
|
10
|
-
fill: "currentColor",
|
|
11
|
-
height: "250",
|
|
12
|
-
preserveAspectRatio: "xMidYMid",
|
|
13
8
|
role: "img",
|
|
14
9
|
viewBox: "0 0 256 250",
|
|
15
10
|
width: "256",
|
|
11
|
+
height: "250",
|
|
12
|
+
fill: "currentColor",
|
|
16
13
|
xmlns: "http://www.w3.org/2000/svg",
|
|
14
|
+
preserveAspectRatio: "xMidYMid",
|
|
15
|
+
"aria-label": "GitHub",
|
|
17
16
|
children: /* @__PURE__ */ jsx("path", { d: "M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46 6.397 1.185 8.746-2.777 8.746-6.158 0-3.052-.12-13.135-.174-23.83-35.61 7.742-43.124-15.103-43.124-15.103-5.823-14.795-14.213-18.73-14.213-18.73-11.613-7.944.876-7.78.876-7.78 12.853.902 19.621 13.19 19.621 13.19 11.417 19.568 29.945 13.911 37.249 10.64 1.149-8.272 4.466-13.92 8.127-17.116-28.431-3.236-58.318-14.212-58.318-63.258 0-13.975 5-25.394 13.188-34.358-1.329-3.224-5.71-16.242 1.24-33.874 0 0 10.749-3.44 35.21 13.121 10.21-2.836 21.16-4.258 32.038-4.307 10.878.049 21.837 1.47 32.066 4.307 24.431-16.56 35.165-13.12 35.165-13.12 6.967 17.63 2.584 30.65 1.255 33.873 8.207 8.964 13.173 20.383 13.173 34.358 0 49.163-29.944 59.988-58.447 63.157 4.591 3.972 8.682 11.762 8.682 23.704 0 17.126-.148 30.91-.148 35.126 0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002 256 57.307 198.691 0 128.001 0Zm-80.06 182.34c-.282.636-1.283.827-2.194.39-.929-.417-1.45-1.284-1.15-1.922.276-.655 1.279-.838 2.205-.399.93.418 1.46 1.293 1.139 1.931Zm6.296 5.618c-.61.566-1.804.303-2.614-.591-.837-.892-.994-2.086-.375-2.66.63-.566 1.787-.301 2.626.591.838.903 1 2.088.363 2.66Zm4.32 7.188c-.785.545-2.067.034-2.86-1.104-.784-1.138-.784-2.503.017-3.05.795-.547 2.058-.055 2.861 1.075.782 1.157.782 2.522-.019 3.08Zm7.304 8.325c-.701.774-2.196.566-3.29-.49-1.119-1.032-1.43-2.496-.726-3.27.71-.776 2.213-.558 3.315.49 1.11 1.03 1.45 2.505.701 3.27Zm9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033-1.448-.439-2.395-1.613-2.103-2.626.301-1.01 1.747-1.484 3.207-1.028 1.446.436 2.396 1.602 2.095 2.622Zm10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95-1.53.034-2.769-.82-2.786-1.86 0-1.065 1.202-1.932 2.733-1.958 1.522-.03 2.768.818 2.768 1.868Zm10.555-.405c.182 1.03-.875 2.088-2.387 2.37-1.485.271-2.861-.365-3.05-1.386-.184-1.056.893-2.114 2.376-2.387 1.514-.263 2.868.356 3.061 1.403Z" })
|
|
18
17
|
});
|
|
19
18
|
/**
|
|
20
19
|
* Google brand icon with official multicolor logo design.
|
|
21
|
-
* Used for Google authentication provider buttons and references.
|
|
22
20
|
*/
|
|
23
21
|
const ICON_GOOGLE = () => /* @__PURE__ */ jsxs("svg", {
|
|
24
|
-
"aria-label": "Google",
|
|
25
|
-
height: "262",
|
|
26
|
-
preserveAspectRatio: "xMidYMid",
|
|
27
22
|
role: "img",
|
|
28
|
-
viewBox: "0 0 256 262",
|
|
29
23
|
width: "256",
|
|
24
|
+
height: "262",
|
|
25
|
+
viewBox: "0 0 256 262",
|
|
30
26
|
xmlns: "http://www.w3.org/2000/svg",
|
|
27
|
+
preserveAspectRatio: "xMidYMid",
|
|
28
|
+
"aria-label": "Google",
|
|
31
29
|
children: [
|
|
32
30
|
/* @__PURE__ */ jsx("path", {
|
|
33
31
|
d: "M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622 38.755 30.023 2.685.268c24.659-22.774 38.875-56.282 38.875-96.027",
|
|
@@ -49,22 +47,201 @@ const ICON_GOOGLE = () => /* @__PURE__ */ jsxs("svg", {
|
|
|
49
47
|
});
|
|
50
48
|
/**
|
|
51
49
|
* Email envelope icon for email-related authentication flows.
|
|
52
|
-
* Used in email verification, password reset, and contact forms.
|
|
53
50
|
*/
|
|
54
51
|
const ICON_EMAIL = () => /* @__PURE__ */ jsx("svg", {
|
|
55
|
-
"aria-label": "Email",
|
|
56
|
-
fill: "none",
|
|
57
52
|
role: "img",
|
|
53
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
54
|
+
fill: "none",
|
|
55
|
+
viewBox: "0 0 24 24",
|
|
56
|
+
"stroke-width": "1.5",
|
|
58
57
|
stroke: "currentColor",
|
|
59
|
-
|
|
58
|
+
"aria-label": "Email",
|
|
59
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
60
|
+
"stroke-linecap": "round",
|
|
61
|
+
"stroke-linejoin": "round",
|
|
62
|
+
d: "M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"
|
|
63
|
+
})
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Apple brand icon for Sign in with Apple.
|
|
67
|
+
*/
|
|
68
|
+
const ICON_APPLE = () => /* @__PURE__ */ jsx("svg", {
|
|
69
|
+
role: "img",
|
|
70
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
71
|
+
viewBox: "0 0 814 1000",
|
|
72
|
+
fill: "currentColor",
|
|
73
|
+
"aria-label": "Apple",
|
|
74
|
+
children: /* @__PURE__ */ jsx("path", { 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" })
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* Discord brand icon.
|
|
78
|
+
*/
|
|
79
|
+
const ICON_DISCORD = () => /* @__PURE__ */ jsx("svg", {
|
|
80
|
+
role: "img",
|
|
60
81
|
viewBox: "0 0 24 24",
|
|
61
82
|
xmlns: "http://www.w3.org/2000/svg",
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
83
|
+
fill: "currentColor",
|
|
84
|
+
"aria-label": "Discord",
|
|
85
|
+
children: /* @__PURE__ */ jsx("path", { d: "M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z" })
|
|
86
|
+
});
|
|
87
|
+
/**
|
|
88
|
+
* Facebook brand icon with gradient.
|
|
89
|
+
*/
|
|
90
|
+
const ICON_FACEBOOK = () => /* @__PURE__ */ jsxs("svg", {
|
|
91
|
+
role: "img",
|
|
92
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
93
|
+
viewBox: "0 0 36 36",
|
|
94
|
+
fill: "url(#facebook_gradient)",
|
|
95
|
+
"aria-label": "Facebook",
|
|
96
|
+
children: [
|
|
97
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", {
|
|
98
|
+
x1: "50%",
|
|
99
|
+
x2: "50%",
|
|
100
|
+
y1: "97.078%",
|
|
101
|
+
y2: "0%",
|
|
102
|
+
id: "facebook_gradient",
|
|
103
|
+
children: [/* @__PURE__ */ jsx("stop", {
|
|
104
|
+
offset: "0%",
|
|
105
|
+
"stop-color": "#0062E0"
|
|
106
|
+
}), /* @__PURE__ */ jsx("stop", {
|
|
107
|
+
offset: "100%",
|
|
108
|
+
"stop-color": "#19AFFF"
|
|
109
|
+
})]
|
|
110
|
+
}) }),
|
|
111
|
+
/* @__PURE__ */ jsx("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" }),
|
|
112
|
+
/* @__PURE__ */ jsx("path", {
|
|
113
|
+
fill: "#FFF",
|
|
114
|
+
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"
|
|
115
|
+
})
|
|
116
|
+
]
|
|
117
|
+
});
|
|
118
|
+
/**
|
|
119
|
+
* LinkedIn brand icon.
|
|
120
|
+
*/
|
|
121
|
+
const ICON_LINKEDIN = () => /* @__PURE__ */ jsx("svg", {
|
|
122
|
+
role: "img",
|
|
123
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
124
|
+
viewBox: "0 0 24 24",
|
|
125
|
+
fill: "currentColor",
|
|
126
|
+
"aria-label": "LinkedIn",
|
|
127
|
+
children: /* @__PURE__ */ jsx("path", { d: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.225 0z" })
|
|
128
|
+
});
|
|
129
|
+
/**
|
|
130
|
+
* Microsoft brand icon with four color squares.
|
|
131
|
+
*/
|
|
132
|
+
const ICON_MICROSOFT = () => /* @__PURE__ */ jsxs("svg", {
|
|
133
|
+
role: "img",
|
|
134
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
135
|
+
viewBox: "0 0 23 23",
|
|
136
|
+
fill: "currentColor",
|
|
137
|
+
"aria-label": "Microsoft",
|
|
138
|
+
children: [
|
|
139
|
+
/* @__PURE__ */ jsx("rect", {
|
|
140
|
+
x: "0",
|
|
141
|
+
y: "0",
|
|
142
|
+
width: "10.58",
|
|
143
|
+
height: "10.58",
|
|
144
|
+
fill: "#F1511B"
|
|
145
|
+
}),
|
|
146
|
+
/* @__PURE__ */ jsx("rect", {
|
|
147
|
+
x: "12.42",
|
|
148
|
+
y: "0",
|
|
149
|
+
width: "10.58",
|
|
150
|
+
height: "10.58",
|
|
151
|
+
fill: "#80CC28"
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ jsx("rect", {
|
|
154
|
+
x: "0",
|
|
155
|
+
y: "12.42",
|
|
156
|
+
width: "10.58",
|
|
157
|
+
height: "10.58",
|
|
158
|
+
fill: "#00ADEF"
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ jsx("rect", {
|
|
161
|
+
x: "12.42",
|
|
162
|
+
y: "12.42",
|
|
163
|
+
width: "10.58",
|
|
164
|
+
height: "10.58",
|
|
165
|
+
fill: "#FFB900"
|
|
166
|
+
})
|
|
167
|
+
]
|
|
168
|
+
});
|
|
169
|
+
/**
|
|
170
|
+
* Slack brand icon.
|
|
171
|
+
*/
|
|
172
|
+
const ICON_SLACK = () => /* @__PURE__ */ jsx("svg", {
|
|
173
|
+
role: "img",
|
|
174
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
175
|
+
viewBox: "0 0 2447.6 2452.5",
|
|
176
|
+
fill: "currentColor",
|
|
177
|
+
"aria-label": "Slack",
|
|
178
|
+
children: /* @__PURE__ */ jsxs("g", {
|
|
179
|
+
"clip-rule": "evenodd",
|
|
180
|
+
"fill-rule": "evenodd",
|
|
181
|
+
children: [
|
|
182
|
+
/* @__PURE__ */ jsx("path", {
|
|
183
|
+
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",
|
|
184
|
+
fill: "#36c5f0"
|
|
185
|
+
}),
|
|
186
|
+
/* @__PURE__ */ jsx("path", {
|
|
187
|
+
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",
|
|
188
|
+
fill: "#2eb67d"
|
|
189
|
+
}),
|
|
190
|
+
/* @__PURE__ */ jsx("path", {
|
|
191
|
+
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",
|
|
192
|
+
fill: "#ecb22e"
|
|
193
|
+
}),
|
|
194
|
+
/* @__PURE__ */ jsx("path", {
|
|
195
|
+
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",
|
|
196
|
+
fill: "#e01e5a"
|
|
197
|
+
})
|
|
198
|
+
]
|
|
66
199
|
})
|
|
67
200
|
});
|
|
201
|
+
/**
|
|
202
|
+
* GitLab brand icon.
|
|
203
|
+
*/
|
|
204
|
+
const ICON_GITLAB = () => /* @__PURE__ */ jsx("svg", {
|
|
205
|
+
role: "img",
|
|
206
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
207
|
+
viewBox: "0 0 24 24",
|
|
208
|
+
fill: "currentColor",
|
|
209
|
+
"aria-label": "GitLab",
|
|
210
|
+
children: /* @__PURE__ */ jsx("path", { d: "m23.6004 9.5927-.0337-.0862L20.3.9814a.851.851 0 0 0-.3362-.405.8748.8748 0 0 0-.9997.0539.8748.8748 0 0 0-.29.4399l-2.2055 6.748H7.5375l-2.2057-6.748a.8573.8573 0 0 0-.29-.4412.8748.8748 0 0 0-.9997-.0537.8585.8585 0 0 0-.3362.4049L.4332 9.5015l-.0325.0862a6.0657 6.0657 0 0 0 2.0119 7.0105l.0113.0087.03.0213 4.976 3.7264 2.462 1.8633 1.4995 1.1321a1.0085 1.0085 0 0 0 1.2197 0l1.4995-1.1321 2.4619-1.8633 5.006-3.7489.0125-.01a6.0682 6.0682 0 0 0 2.0094-7.003z" })
|
|
211
|
+
});
|
|
212
|
+
/**
|
|
213
|
+
* Reddit brand icon.
|
|
214
|
+
*/
|
|
215
|
+
const ICON_REDDIT = () => /* @__PURE__ */ jsx("svg", {
|
|
216
|
+
role: "img",
|
|
217
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
218
|
+
viewBox: "0 0 24 24",
|
|
219
|
+
fill: "currentColor",
|
|
220
|
+
"aria-label": "Reddit",
|
|
221
|
+
children: /* @__PURE__ */ jsx("path", { d: "M12 0C5.373 0 0 5.373 0 12c0 3.314 1.343 6.314 3.515 8.485l-2.286 2.286C.775 23.225 1.097 24 1.738 24H12c6.627 0 12-5.373 12-12S18.627 0 12 0Zm4.388 3.199c1.104 0 1.999.895 1.999 1.999 0 1.105-.895 2-1.999 2-.946 0-1.739-.657-1.947-1.539v.002c-1.147.162-2.032 1.15-2.032 2.341v.007c1.776.067 3.4.567 4.686 1.363.473-.363 1.064-.58 1.707-.58 1.547 0 2.802 1.254 2.802 2.802 0 1.117-.655 2.081-1.601 2.531-.088 3.256-3.637 5.876-7.997 5.876-4.361 0-7.905-2.617-7.998-5.87-.954-.447-1.614-1.415-1.614-2.538 0-1.548 1.255-2.802 2.803-2.802.645 0 1.239.218 1.712.585 1.275-.79 2.881-1.291 4.64-1.365v-.01c0-1.663 1.263-3.034 2.88-3.207.188-.911.993-1.595 1.959-1.595Zm-8.085 8.376c-.784 0-1.459.78-1.506 1.797-.047 1.016.64 1.429 1.426 1.429.786 0 1.371-.369 1.418-1.385.047-1.017-.553-1.841-1.338-1.841Zm7.406 0c-.786 0-1.385.824-1.338 1.841.047 1.017.634 1.385 1.418 1.385.785 0 1.473-.413 1.426-1.429-.046-1.017-.721-1.797-1.506-1.797Zm-3.703 4.013c-.974 0-1.907.048-2.77.135-.147.015-.241.168-.183.305.483 1.154 1.622 1.964 2.953 1.964 1.33 0 2.47-.81 2.953-1.964.057-.137-.037-.29-.184-.305-.863-.087-1.795-.135-2.769-.135Z" })
|
|
222
|
+
});
|
|
223
|
+
/**
|
|
224
|
+
* Spotify brand icon.
|
|
225
|
+
*/
|
|
226
|
+
const ICON_SPOTIFY = () => /* @__PURE__ */ jsx("svg", {
|
|
227
|
+
role: "img",
|
|
228
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
229
|
+
viewBox: "0 0 24 24",
|
|
230
|
+
fill: "currentColor",
|
|
231
|
+
"aria-label": "Spotify",
|
|
232
|
+
children: /* @__PURE__ */ jsx("path", { d: "M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z" })
|
|
233
|
+
});
|
|
234
|
+
/**
|
|
235
|
+
* Twitch brand icon.
|
|
236
|
+
*/
|
|
237
|
+
const ICON_TWITCH = () => /* @__PURE__ */ jsx("svg", {
|
|
238
|
+
role: "img",
|
|
239
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
240
|
+
viewBox: "0 0 24 24",
|
|
241
|
+
fill: "currentColor",
|
|
242
|
+
"aria-label": "Twitch",
|
|
243
|
+
children: /* @__PURE__ */ jsx("path", { d: "M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0L1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143l-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714Z" })
|
|
244
|
+
});
|
|
68
245
|
|
|
69
246
|
//#endregion
|
|
70
|
-
export { ICON_EMAIL, ICON_GITHUB, ICON_GOOGLE };
|
|
247
|
+
export { ICON_APPLE, ICON_DISCORD, ICON_EMAIL, ICON_FACEBOOK, ICON_GITHUB, ICON_GITLAB, ICON_GOOGLE, ICON_LINKEDIN, ICON_MICROSOFT, ICON_REDDIT, ICON_SLACK, ICON_SPOTIFY, ICON_TWITCH };
|