Files
netris-nestri/packages/auth/src/ui/select.tsx
2026-08-06 22:13:51 +03:00

202 lines
7.0 KiB
TypeScript

/**
* The UI that's displayed when loading the root page of the OpenAuth server. You can configure
* which providers should be displayed in the select UI.
*
* ```ts
* import { Select } from "@openauthjs/openauth/ui/select"
*
* export default issuer({
* select: Select({
* providers: {
* github: {
* hide: true
* },
* google: {
* display: "Google"
* }
* }
* })
* // ...
* })
* ```
*
* @packageDocumentation
*/
/** @jsxImportSource hono/jsx */
import { Layout } from './base.js';
import { ICON_GITHUB, ICON_GOOGLE } from './icon.js';
export interface SelectProps {
/**
* An object with all the providers and their config; where the key is the provider name.
*
* @example
* ```ts
* {
* github: {
* hide: true
* },
* google: {
* display: "Google"
* }
* }
* ```
*/
providers?: Record<
string,
{
/**
* Whether to hide the provider from the select UI.
* @default false
*/
hide?: boolean;
/**
* The display name of the provider.
*/
display?: string;
}
>;
}
export function Select(props?: SelectProps) {
return async (providers: Record<string, string>, _req: Request): Promise<Response> => {
const jsx = (
<Layout>
<div data-component="form">
{Object.entries(providers).map(([key, type]) => {
const match = props?.providers?.[key];
if (match?.hide) return;
const icon = ICON[key];
return (
<a href={`/${key}/authorize`} data-component="button" data-color="ghost">
{icon && <i data-slot="icon">{icon}</i>}
Continue with {match?.display || DISPLAY[type] || type}
</a>
);
})}
</div>
</Layout>
);
return new Response(jsx.toString(), {
headers: {
'Content-Type': 'text/html'
}
});
};
}
const DISPLAY: Record<string, string> = {
twitch: 'Twitch',
google: 'Google',
github: 'GitHub',
apple: 'Apple',
x: 'X',
facebook: 'Facebook',
microsoft: 'Microsoft',
slack: 'Slack'
};
const ICON: Record<string, any> = {
code: (
<svg
fill="currentColor"
viewBox="0 0 52 52"
data-name="Layer 1"
xmlns="http://www.w3.org/2000/svg">
<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"
fill-rule="evenodd"
/>
</svg>
),
password: (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path
fill-rule="evenodd"
d="M12 1.5a5.25 5.25 0 0 0-5.25 5.25v3a3 3 0 0 0-3 3v6.75a3 3 0 0 0 3 3h10.5a3 3 0 0 0 3-3v-6.75a3 3 0 0 0-3-3v-3c0-2.9-2.35-5.25-5.25-5.25Zm3.75 8.25v-3a3.75 3.75 0 1 0-7.5 0v3h7.5Z"
clip-rule="evenodd"
/>
</svg>
),
twitch: (
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<path
fill="currentColor"
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"></path>
</svg>
),
google: ICON_GOOGLE,
github: ICON_GITHUB,
apple: (
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 1000">
<path
fill="currentColor"
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 "
/>
</svg>
),
x: (
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1227">
<path
fill="currentColor"
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"
/>
</svg>
),
microsoft: (
<svg
role="img"
viewBox="0 0 256 256"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid">
<path fill="#F1511B" d="M121.666 121.666H0V0h121.666z" />
<path fill="#80CC28" d="M256 121.666H134.335V0H256z" />
<path fill="#00ADEF" d="M121.663 256.002H0V134.336h121.663z" />
<path fill="#FBBC09" d="M256 256.002H134.335V134.336H256z" />
</svg>
),
facebook: (
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" fill="url(#a)">
<defs>
<linearGradient x1="50%" x2="50%" y1="97.078%" y2="0%" id="a">
<stop offset="0%" stop-color="#0062E0" />
<stop offset="100%" stop-color="#19AFFF" />
</linearGradient>
</defs>
<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" />
<path
fill="#FFF"
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"
/>
</svg>
),
slack: (
<svg
role="img"
enable-background="new 0 0 2447.6 2452.5"
viewBox="0 0 2447.6 2452.5"
xmlns="http://www.w3.org/2000/svg">
<g clip-rule="evenodd" fill-rule="evenodd">
<path
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"
fill="#36c5f0"
/>
<path
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"
fill="#2eb67d"
/>
<path
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"
fill="#ecb22e"
/>
<path
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"
fill="#e01e5a"
/>
</g>
</svg>
)
};