@oussemasahbeni/keycloakify-login-shadcn 250004.0.8 → 250004.0.9
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/keycloak-theme/components/ui/alert.tsx +69 -61
- package/keycloak-theme/components/ui/button.tsx +44 -38
- package/keycloak-theme/components/ui/card.tsx +60 -45
- package/keycloak-theme/components/ui/checkbox.tsx +24 -22
- package/keycloak-theme/components/ui/dropdown-menu.tsx +231 -176
- package/keycloak-theme/components/ui/field.tsx +51 -48
- package/keycloak-theme/components/ui/input-otp.tsx +56 -49
- package/keycloak-theme/components/ui/input.tsx +18 -21
- package/keycloak-theme/components/ui/label.tsx +19 -20
- package/keycloak-theme/components/ui/radio-group.tsx +27 -25
- package/keycloak-theme/components/ui/select.tsx +160 -121
- package/keycloak-theme/components/ui/separator.tsx +23 -23
- package/keycloak-theme/components/ui/tooltip.tsx +54 -24
- package/keycloak-theme/login/KcPage.tsx +0 -1
- package/keycloak-theme/login/components/Template/Template.tsx +2 -2
- package/keycloak-theme/login/index.css +3 -20
- package/keycloak-theme/login/pages/login/Form.tsx +49 -51
- package/keycloak-theme/login/pages/login/SocialProviders.tsx +9 -4
- package/keycloak-theme/login/pages/login/providers/github.svg +4 -3
- package/keycloak-theme/login/pages/login/providers/x.svg +4 -3
- package/keycloak-theme/login/pages/login/useProviderLogos.tsx +2 -3
- package/keycloak-theme/login/styleLevelCustomization.tsx +1 -0
- package/package.json +1 -1
|
@@ -1,30 +1,60 @@
|
|
|
1
|
-
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
|
2
|
-
import * as React from "react"
|
|
1
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
|
2
|
+
import * as React from "react"
|
|
3
3
|
|
|
4
|
-
import { cn } from
|
|
4
|
+
import { cn } from '../lib/utils'
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
function TooltipProvider({
|
|
7
|
+
delayDuration = 0,
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
|
10
|
+
return (
|
|
11
|
+
<TooltipPrimitive.Provider
|
|
12
|
+
data-slot="tooltip-provider"
|
|
13
|
+
delayDuration={delayDuration}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
7
18
|
|
|
8
|
-
|
|
19
|
+
function Tooltip({
|
|
20
|
+
...props
|
|
21
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
|
22
|
+
return (
|
|
23
|
+
<TooltipProvider>
|
|
24
|
+
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
25
|
+
</TooltipProvider>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
9
28
|
|
|
10
|
-
|
|
29
|
+
function TooltipTrigger({
|
|
30
|
+
...props
|
|
31
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
|
32
|
+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
|
33
|
+
}
|
|
11
34
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
function TooltipContent({
|
|
36
|
+
className,
|
|
37
|
+
sideOffset = 0,
|
|
38
|
+
children,
|
|
39
|
+
...props
|
|
40
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
|
41
|
+
return (
|
|
42
|
+
<TooltipPrimitive.Portal>
|
|
43
|
+
<TooltipPrimitive.Content
|
|
44
|
+
data-slot="tooltip-content"
|
|
45
|
+
sideOffset={sideOffset}
|
|
46
|
+
className={cn(
|
|
47
|
+
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
48
|
+
className
|
|
49
|
+
)}
|
|
50
|
+
{...props}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
<TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px]" />
|
|
54
|
+
</TooltipPrimitive.Content>
|
|
55
|
+
</TooltipPrimitive.Portal>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
|
|
29
60
|
|
|
30
|
-
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
|
@@ -4,7 +4,6 @@ import type { ReactNode } from "react";
|
|
|
4
4
|
import { assert } from "tsafe/assert";
|
|
5
5
|
import { type KcContext, KcContextProvider } from "./KcContext";
|
|
6
6
|
import { I18nProvider } from "./i18n";
|
|
7
|
-
import "./index.css";
|
|
8
7
|
import { PageIndex } from "./pages/PageIndex";
|
|
9
8
|
import { useStyleLevelCustomization } from "./styleLevelCustomization";
|
|
10
9
|
|
|
@@ -108,7 +108,7 @@ export function Template(props: {
|
|
|
108
108
|
<div className="flex flex-1 items-start lg:items-center justify-center lg:mt-0 ">
|
|
109
109
|
<div className="w-full max-w-xl ">
|
|
110
110
|
<Card className=" shadow-none bg-transparent lg:bg-card border-0 lg:rounded-lg lg:border lg:shadow-sm rounded-t-2xl">
|
|
111
|
-
<CardHeader className="text-center
|
|
111
|
+
<CardHeader className="text-center">
|
|
112
112
|
<CardTitle>
|
|
113
113
|
{(() => {
|
|
114
114
|
const node = !(
|
|
@@ -182,7 +182,7 @@ export function Template(props: {
|
|
|
182
182
|
})()}
|
|
183
183
|
</CardTitle>
|
|
184
184
|
</CardHeader>
|
|
185
|
-
<CardContent
|
|
185
|
+
<CardContent >
|
|
186
186
|
<div id="kc-content">
|
|
187
187
|
<div id="kc-content-wrapper">
|
|
188
188
|
{displayMessage &&
|
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
@import "tailwindcss";
|
|
4
4
|
|
|
5
|
+
@source "../**/*.{ts,tsx}";
|
|
6
|
+
|
|
5
7
|
@custom-variant dark (&:is(.dark *));
|
|
6
8
|
|
|
7
9
|
@theme {
|
|
8
10
|
--font-geist: Geist, sans-serif;
|
|
9
11
|
|
|
10
|
-
--radius-lg: var(--radius);
|
|
11
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
12
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
13
|
-
|
|
14
12
|
--color-background: var(--background);
|
|
15
13
|
--color-foreground: var(--foreground);
|
|
16
14
|
--color-card: var(--card);
|
|
@@ -70,21 +68,6 @@
|
|
|
70
68
|
@apply text-right;
|
|
71
69
|
}
|
|
72
70
|
|
|
73
|
-
/* .kcHeaderWrapperClass {
|
|
74
|
-
@apply text-3xl font-bold underline;
|
|
75
|
-
} */
|
|
76
|
-
/* input[type="checkbox"],
|
|
77
|
-
input[type="radio"] {
|
|
78
|
-
margin: 2px;
|
|
79
|
-
vertical-align: middle;
|
|
80
|
-
line-height: normal;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
input[type="checkbox"]:checked,
|
|
84
|
-
input[type="radio"]:checked {
|
|
85
|
-
@apply accent-primary;
|
|
86
|
-
} */
|
|
87
|
-
|
|
88
71
|
.required {
|
|
89
72
|
@apply text-red-600;
|
|
90
73
|
}
|
|
@@ -141,7 +124,7 @@
|
|
|
141
124
|
--muted-foreground: oklch(0.708 0 0);
|
|
142
125
|
--accent: oklch(0.269 0 0);
|
|
143
126
|
--accent-foreground: oklch(0.985 0 0);
|
|
144
|
-
--destructive: oklch(
|
|
127
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
145
128
|
--border: oklch(1 0 0 / 10%);
|
|
146
129
|
--input: oklch(1 0 0 / 15%);
|
|
147
130
|
--ring: oklch(0.556 0 0);
|
|
@@ -49,8 +49,8 @@ export function Form() {
|
|
|
49
49
|
{!kcContext.realm.loginWithEmailAllowed
|
|
50
50
|
? msg("email")
|
|
51
51
|
: !kcContext.realm.registrationEmailAsUsername
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
? msg("usernameOrEmail")
|
|
53
|
+
: msg("username")}
|
|
54
54
|
</FieldLabel>
|
|
55
55
|
<Input
|
|
56
56
|
tabIndex={2}
|
|
@@ -69,21 +69,21 @@ export function Form() {
|
|
|
69
69
|
"username",
|
|
70
70
|
"password"
|
|
71
71
|
) && (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
72
|
+
<FieldError>
|
|
73
|
+
<span
|
|
74
|
+
id="input-error"
|
|
75
|
+
aria-live="polite"
|
|
76
|
+
dangerouslySetInnerHTML={{
|
|
77
|
+
__html: kcSanitize(
|
|
78
|
+
kcContext.messagesPerField.getFirstError(
|
|
79
|
+
"username",
|
|
80
|
+
"password"
|
|
81
|
+
)
|
|
81
82
|
)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
)}
|
|
83
|
+
}}
|
|
84
|
+
/>
|
|
85
|
+
</FieldError>
|
|
86
|
+
)}
|
|
87
87
|
</Field>
|
|
88
88
|
)}
|
|
89
89
|
|
|
@@ -108,46 +108,44 @@ export function Form() {
|
|
|
108
108
|
"username",
|
|
109
109
|
"password"
|
|
110
110
|
) && (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
111
|
+
<FieldError>
|
|
112
|
+
<span
|
|
113
|
+
id="input-error"
|
|
114
|
+
aria-live="polite"
|
|
115
|
+
dangerouslySetInnerHTML={{
|
|
116
|
+
__html: kcSanitize(
|
|
117
|
+
kcContext.messagesPerField.getFirstError(
|
|
118
|
+
"username",
|
|
119
|
+
"password"
|
|
120
|
+
)
|
|
120
121
|
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
)}
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
124
|
+
</FieldError>
|
|
125
|
+
)}
|
|
126
126
|
</Field>
|
|
127
127
|
|
|
128
128
|
<div className=" space-y-1 my-3 flex justify-between text-xs ">
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
/>
|
|
129
|
+
{kcContext.realm.rememberMe &&
|
|
130
|
+
!kcContext.usernameHidden && (
|
|
131
|
+
<div className="flex items-center space-x-2 ">
|
|
132
|
+
<Checkbox
|
|
133
|
+
tabIndex={5}
|
|
134
|
+
id="rememberMe"
|
|
135
|
+
name="rememberMe"
|
|
136
|
+
defaultChecked={
|
|
137
|
+
!!kcContext.login.rememberMe
|
|
138
|
+
}
|
|
139
|
+
/>
|
|
141
140
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
</div>
|
|
141
|
+
<Label
|
|
142
|
+
htmlFor="rememberMe"
|
|
143
|
+
className="text-sm font-medium cursor-pointer"
|
|
144
|
+
>
|
|
145
|
+
{msg("rememberMe")}
|
|
146
|
+
</Label>
|
|
147
|
+
</div>
|
|
148
|
+
)}
|
|
151
149
|
<div className="link-style ">
|
|
152
150
|
{kcContext.realm.resetPasswordAllowed && (
|
|
153
151
|
<span className=" underline-offset-4 hover:underline">
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { cn } from '@/components/lib/utils';
|
|
1
2
|
import { Button } from "@/components/ui/button";
|
|
2
3
|
import { kcSanitize } from "@keycloakify/login-ui/kcSanitize";
|
|
3
4
|
import { clsx } from "@keycloakify/login-ui/tools/clsx";
|
|
@@ -39,7 +40,7 @@ export function SocialProviders() {
|
|
|
39
40
|
<div className="mt-px flex-auto border-t"></div>
|
|
40
41
|
</div>
|
|
41
42
|
<ul
|
|
42
|
-
className={`mt-4! grid gap-
|
|
43
|
+
className={`mt-4! grid gap-3 sm:grid-cols-1 ${(kcContext.social?.providers?.length ?? 0) > 3 ? "sm:grid-cols-2" : ""}`}
|
|
43
44
|
>
|
|
44
45
|
{kcContext.social.providers.map((...[p, , providers]) => (
|
|
45
46
|
<li key={p.alias}>
|
|
@@ -49,9 +50,9 @@ export function SocialProviders() {
|
|
|
49
50
|
className={clsx(
|
|
50
51
|
kcClsx(
|
|
51
52
|
providers.length > 3 &&
|
|
52
|
-
|
|
53
|
+
"kcFormSocialAccountGridItem"
|
|
53
54
|
),
|
|
54
|
-
"flex items-center justify-center gap-
|
|
55
|
+
"flex items-center justify-center gap-3 "
|
|
55
56
|
)}
|
|
56
57
|
type="button"
|
|
57
58
|
href={p.loginUrl}
|
|
@@ -61,7 +62,11 @@ export function SocialProviders() {
|
|
|
61
62
|
<img
|
|
62
63
|
src={providerLogos[p.alias]}
|
|
63
64
|
alt={`${p.displayName} logo`}
|
|
64
|
-
className={
|
|
65
|
+
className={cn(
|
|
66
|
+
"h-full w-auto",
|
|
67
|
+
// Invert specific icons in dark mode
|
|
68
|
+
(p.alias === "github" || p.alias === "x" || p.alias === "twitter") && "dark:invert"
|
|
69
|
+
)}
|
|
65
70
|
/>
|
|
66
71
|
) : (
|
|
67
72
|
// Fallback to the original iconClasses if the logo is not defined
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
<svg
|
|
2
|
-
<
|
|
3
|
-
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
2
|
+
<path
|
|
3
|
+
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
|
|
4
|
+
fill="currentColor" />
|
|
4
5
|
</svg>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
<path
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" role="img"
|
|
2
|
+
aria-hidden="true">
|
|
3
|
+
<path
|
|
4
|
+
d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" />
|
|
4
5
|
</svg>
|
|
@@ -24,11 +24,10 @@ const useProviderLogos: () => Record<string, string> = () => ({
|
|
|
24
24
|
gitlab: gitlabLogo,
|
|
25
25
|
google: googleLogo,
|
|
26
26
|
instagram: instagramLogo,
|
|
27
|
-
|
|
27
|
+
linkedin: linkedinLogo,
|
|
28
28
|
microsoft: microsoftLogo,
|
|
29
29
|
oidc: oidcLogo,
|
|
30
|
-
|
|
31
|
-
"openshift-v4": openshiftLogo,
|
|
30
|
+
openshift: openshiftLogo,
|
|
32
31
|
paypal: paypalLogo,
|
|
33
32
|
slack: slackLogo,
|
|
34
33
|
stackoverflow: stackoverflowLogo,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ThemeProvider } from "@/components/theme-provider";
|
|
2
2
|
import type { ClassKey } from "@keycloakify/login-ui/useKcClsx";
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
|
+
import "./index.css";
|
|
4
5
|
import { useKcContext } from "./KcContext";
|
|
5
6
|
import { getTheme } from "./shared/getColorScheme";
|
|
6
7
|
|