uibee 3.3.0 → 3.3.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/components/alert/alert.d.ts +15 -0
- package/dist/components/alert/alert.js +29 -0
- package/dist/components/badge/badge.d.ts +16 -0
- package/dist/components/badge/badge.js +26 -0
- package/dist/components/buttons/button.d.ts +25 -0
- package/dist/components/buttons/button.js +44 -0
- package/dist/components/code/code.d.ts +23 -0
- package/dist/components/code/code.js +39 -0
- package/dist/components/confirm/confirmPopup.d.ts +23 -0
- package/dist/components/confirm/confirmPopup.js +52 -0
- package/dist/components/container/accordion.d.ts +25 -0
- package/dist/components/container/accordion.js +41 -0
- package/dist/components/container/card.d.ts +13 -0
- package/dist/components/container/card.js +10 -0
- package/dist/components/container/expandableCard.d.ts +32 -0
- package/dist/components/container/expandableCard.js +70 -0
- package/dist/components/container/glassCard.d.ts +13 -0
- package/dist/components/container/glassCard.js +10 -0
- package/dist/components/container/highlight.d.ts +10 -0
- package/dist/components/container/highlight.js +10 -0
- package/dist/components/container/iconBubble.d.ts +25 -0
- package/dist/components/container/iconBubble.js +21 -0
- package/dist/components/container/leftBarPanel.d.ts +15 -0
- package/dist/components/container/leftBarPanel.js +10 -0
- package/dist/components/container/page.d.ts +15 -0
- package/dist/components/container/page.js +16 -0
- package/dist/components/container/pulseDot.d.ts +12 -0
- package/dist/components/container/pulseDot.js +23 -0
- package/dist/components/container/statCard.d.ts +18 -0
- package/dist/components/container/statCard.js +25 -0
- package/dist/components/container/tabs.d.ts +35 -0
- package/dist/components/container/tabs.js +36 -0
- package/dist/components/empty/emptyState.d.ts +19 -0
- package/dist/components/empty/emptyState.js +27 -0
- package/dist/components/footer/footer.d.ts +49 -0
- package/dist/components/footer/footer.js +109 -0
- package/dist/components/footer/loginContent.d.ts +18 -0
- package/dist/components/footer/loginContent.js +138 -0
- package/dist/components/inputs/checkbox.d.ts +20 -0
- package/dist/components/inputs/checkbox.js +76 -0
- package/dist/components/inputs/fileInput.d.ts +19 -0
- package/dist/components/inputs/fileInput.js +108 -0
- package/dist/components/inputs/input.d.ts +16 -0
- package/dist/components/inputs/input.js +157 -0
- package/dist/components/inputs/multiSelect.d.ts +37 -0
- package/dist/components/inputs/multiSelect.js +99 -0
- package/dist/components/inputs/radio.d.ts +20 -0
- package/dist/components/inputs/radio.js +70 -0
- package/dist/components/inputs/range.d.ts +14 -0
- package/dist/components/inputs/range.js +60 -0
- package/dist/components/inputs/searchInput.d.ts +11 -0
- package/dist/components/inputs/searchInput.js +56 -0
- package/dist/components/inputs/select.d.ts +42 -0
- package/dist/components/inputs/select.js +164 -0
- package/dist/components/inputs/shared/colorPickerPopup.js +293 -0
- package/dist/components/inputs/shared/dateTimePickerPopup.js +225 -0
- package/dist/components/inputs/shared/fieldWrapper.js +33 -0
- package/dist/components/inputs/shared/index.js +6 -0
- package/dist/components/inputs/shared/inputError.js +17 -0
- package/dist/components/inputs/shared/inputInfo.js +13 -0
- package/dist/components/inputs/shared/inputLabel.js +19 -0
- package/dist/components/inputs/switch.d.ts +14 -0
- package/dist/components/inputs/switch.js +37 -0
- package/dist/components/inputs/tagInput.d.ts +31 -0
- package/dist/components/inputs/tagInput.js +72 -0
- package/dist/components/inputs/textarea.d.ts +14 -0
- package/dist/components/inputs/textarea.js +76 -0
- package/dist/components/inputs/toggle.d.ts +21 -0
- package/dist/components/inputs/toggle.js +33 -0
- package/dist/components/login/loginPage.d.ts +15 -0
- package/dist/components/login/loginPage.js +80 -0
- package/dist/components/logo/logo.d.ts +9 -0
- package/dist/components/logo/logo.js +138 -0
- package/dist/components/logo/logoSmall.d.ts +4 -0
- package/dist/components/logo/logoSmall.js +56 -0
- package/dist/components/markdownrender/markdownRender.d.ts +16 -0
- package/dist/components/markdownrender/markdownRender.js +59 -0
- package/dist/components/modal/modal.d.ts +22 -0
- package/dist/components/modal/modal.js +59 -0
- package/dist/components/navbar/bubble.js +36 -0
- package/dist/components/navbar/navbar.d.ts +50 -0
- package/dist/components/navbar/navbar.js +99 -0
- package/dist/components/navbar/navbarDropdown.d.ts +15 -0
- package/dist/components/navbar/navbarDropdown.js +63 -0
- package/dist/components/navbar/navbarItem.d.ts +23 -0
- package/dist/components/navbar/navbarItem.js +38 -0
- package/dist/components/sidebar/sidebar.d.ts +34 -0
- package/dist/components/sidebar/sidebar.js +135 -0
- package/dist/components/spinner/spinner.d.ts +11 -0
- package/dist/components/spinner/spinner.js +16 -0
- package/dist/components/table/body.js +253 -0
- package/dist/components/table/constants.js +58 -0
- package/dist/components/table/empty.js +24 -0
- package/dist/components/table/format.js +39 -0
- package/dist/components/table/header.js +109 -0
- package/dist/components/table/menu.d.ts +18 -0
- package/dist/components/table/menu.js +76 -0
- package/dist/components/table/pagination.d.ts +14 -0
- package/dist/components/table/pagination.js +130 -0
- package/dist/components/table/skeleton.js +39 -0
- package/dist/components/table/table.d.ts +7 -0
- package/dist/components/table/table.js +213 -0
- package/dist/components/table/types.d.ts +52 -0
- package/dist/components/table/utils.js +9 -0
- package/dist/components/toast/toastItem.js +61 -0
- package/dist/components/toast/toaster.d.ts +13 -0
- package/dist/components/toast/toaster.js +117 -0
- package/dist/components/toggle/language.d.ts +10 -0
- package/dist/components/toggle/language.js +34 -0
- package/dist/components/toggle/theme.d.ts +8 -0
- package/dist/components/toggle/theme.js +135 -0
- package/dist/components/version/version.d.ts +13 -0
- package/dist/components/version/version.js +19 -0
- package/dist/components/vulnerability/constants.d.ts +4 -0
- package/dist/components/vulnerability/constants.js +17 -0
- package/dist/components/vulnerability/severityPill.d.ts +15 -0
- package/dist/components/vulnerability/severityPill.js +20 -0
- package/dist/{style.css → globals.css} +152 -226
- package/dist/hooks/useClickOutside.d.ts +6 -0
- package/dist/{useClickOutside-Cmp-RsP3.js → hooks/useClickOutside.js} +1 -1
- package/dist/hooks/useDarkMode.d.ts +4 -0
- package/dist/hooks/useDarkMode.js +19 -0
- package/dist/hooks/useVisibility.d.ts +7 -0
- package/dist/hooks/useVisibility.js +25 -0
- package/dist/icons/icons.d.ts +420 -0
- package/dist/{icons-lZYQ6Vlr.js → icons/icons.js} +1 -1
- package/dist/src/components/index.d.ts +51 -905
- package/dist/src/components/index.js +49 -4179
- package/dist/src/hooks/index.d.ts +3 -14
- package/dist/src/hooks/index.js +3 -42
- package/dist/src/icons/index.d.ts +1 -419
- package/dist/src/icons/index.js +1 -1
- package/dist/src/styles/index.js +1 -1
- package/dist/src/utils/index.d.ts +5 -37
- package/dist/src/utils/index.js +5 -124
- package/dist/utils/auth/callback.d.ts +14 -0
- package/dist/utils/auth/callback.js +53 -0
- package/dist/utils/auth/getDomain.js +6 -0
- package/dist/utils/auth/login.d.ts +12 -0
- package/dist/utils/auth/login.js +17 -0
- package/dist/utils/auth/logout.d.ts +10 -0
- package/dist/utils/auth/logout.js +20 -0
- package/dist/utils/auth/token.d.ts +10 -0
- package/dist/utils/auth/token.js +30 -0
- package/dist/utils/logoConsoleOutput/logoConsoleOutput.d.ts +4 -0
- package/dist/utils/logoConsoleOutput/logoConsoleOutput.js +11 -0
- package/package.json +1 -1
- package/src/components/buttons/button.tsx +2 -0
- package/src/components/footer/footer.tsx +60 -42
- package/src/components/index.ts +0 -1
- package/src/components/inputs/checkbox.tsx +2 -0
- package/src/components/inputs/input.tsx +2 -0
- package/src/components/inputs/radio.tsx +2 -0
- package/src/components/inputs/range.tsx +2 -0
- package/src/components/inputs/shared/colorPickerPopup.tsx +2 -0
- package/src/components/inputs/shared/dateTimePickerPopup.tsx +2 -0
- package/src/components/inputs/textarea.tsx +2 -0
- package/src/components/inputs/toggle.tsx +2 -0
- package/src/components/toast/toastItem.tsx +2 -0
- package/src/globals.css +5 -0
- package/tsdown.config.ts +1 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AuthCallbackProps } from "uibee/utils";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/auth/callback.d.ts
|
|
4
|
+
declare function authCallback({
|
|
5
|
+
req,
|
|
6
|
+
tokenURL,
|
|
7
|
+
clientID,
|
|
8
|
+
clientSecret,
|
|
9
|
+
redirectPath,
|
|
10
|
+
userInfoURL,
|
|
11
|
+
tokenRedirectPath
|
|
12
|
+
}: AuthCallbackProps): Promise<Response>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { authCallback as default };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { getDomain } from "./getDomain.js";
|
|
2
|
+
import { NextResponse } from "next/server.js";
|
|
3
|
+
//#region src/utils/auth/callback.ts
|
|
4
|
+
async function authCallback({ req, tokenURL, clientID, clientSecret, redirectPath, userInfoURL, tokenRedirectPath }) {
|
|
5
|
+
const domain = getDomain(req);
|
|
6
|
+
const searchParams = new URL(req.url).searchParams;
|
|
7
|
+
if (!searchParams) return NextResponse.json({ error: "No search parameters found." }, { status: 400 });
|
|
8
|
+
const code = searchParams.get("code");
|
|
9
|
+
if (!code) return NextResponse.json({ error: "No authorization code found." }, { status: 400 });
|
|
10
|
+
try {
|
|
11
|
+
const tokenResponse = await fetch(tokenURL, {
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
14
|
+
body: new URLSearchParams({
|
|
15
|
+
client_id: clientID,
|
|
16
|
+
client_secret: clientSecret,
|
|
17
|
+
code,
|
|
18
|
+
redirect_uri: `${domain}${redirectPath}`,
|
|
19
|
+
grant_type: "authorization_code"
|
|
20
|
+
}).toString()
|
|
21
|
+
});
|
|
22
|
+
const tokenResponseBody = await tokenResponse.text();
|
|
23
|
+
if (!tokenResponse.ok) return new Response(JSON.stringify(`Failed to obtain token: ${tokenResponseBody}`), {
|
|
24
|
+
status: 500,
|
|
25
|
+
headers: { "Content-Type": "application/json" }
|
|
26
|
+
});
|
|
27
|
+
const token = JSON.parse(tokenResponseBody);
|
|
28
|
+
const userInfoResponse = await fetch(userInfoURL, { headers: { Authorization: `Bearer ${token.access_token}` } });
|
|
29
|
+
if (!userInfoResponse.ok) {
|
|
30
|
+
const userInfoError = await userInfoResponse.text();
|
|
31
|
+
return new Response(`No user info found: ${userInfoError}`, {
|
|
32
|
+
status: 500,
|
|
33
|
+
headers: { "Content-Type": "application/json" }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const userInfo = await userInfoResponse.json();
|
|
37
|
+
const redirectUrl = new URL(`${domain}${tokenRedirectPath}`);
|
|
38
|
+
redirectUrl.search = new URLSearchParams({
|
|
39
|
+
id: userInfo.sub,
|
|
40
|
+
name: userInfo.name,
|
|
41
|
+
username: userInfo.nickname,
|
|
42
|
+
email: userInfo.email,
|
|
43
|
+
groups: userInfo.groups.join(","),
|
|
44
|
+
access_token: token.access_token
|
|
45
|
+
}).toString();
|
|
46
|
+
return NextResponse.redirect(redirectUrl.toString());
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.error("Error during OAuth flow:", err.message);
|
|
49
|
+
return NextResponse.json({ error: "Authentication failed" }, { status: 500 });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { authCallback as default };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/utils/auth/getDomain.ts
|
|
2
|
+
function getDomain(req) {
|
|
3
|
+
return `${req.headers.get("x-forwarded-proto") ?? new URL(req.url).protocol.replace(":", "")}://${req.headers.get("host") ?? req.headers.get("x-forwarded-host") ?? new URL(req.url).host}`;
|
|
4
|
+
}
|
|
5
|
+
//#endregion
|
|
6
|
+
export { getDomain };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NextResponse } from "next/server.js";
|
|
2
|
+
import { AuthLoginProps } from "uibee/utils";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/auth/login.d.ts
|
|
5
|
+
declare function AuthLogin({
|
|
6
|
+
req,
|
|
7
|
+
clientID,
|
|
8
|
+
redirectPath,
|
|
9
|
+
authURL
|
|
10
|
+
}: AuthLoginProps): Promise<NextResponse<unknown>>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { AuthLogin as default };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getDomain } from "./getDomain.js";
|
|
2
|
+
import { NextResponse } from "next/server.js";
|
|
3
|
+
//#region src/utils/auth/login.ts
|
|
4
|
+
async function AuthLogin({ req, clientID, redirectPath, authURL }) {
|
|
5
|
+
const domain = getDomain(req);
|
|
6
|
+
const state = Math.random().toString(36).substring(5);
|
|
7
|
+
const authQueryParams = new URLSearchParams({
|
|
8
|
+
client_id: clientID,
|
|
9
|
+
redirect_uri: `${domain}${redirectPath}`,
|
|
10
|
+
response_type: "code",
|
|
11
|
+
scope: "openid profile email",
|
|
12
|
+
state
|
|
13
|
+
}).toString();
|
|
14
|
+
return NextResponse.redirect(`${authURL}?${authQueryParams}`);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { AuthLogin as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NextResponse } from "next/server.js";
|
|
2
|
+
import { AuthLogoutProps } from "uibee/utils";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/auth/logout.d.ts
|
|
5
|
+
declare function AuthLogout({
|
|
6
|
+
req,
|
|
7
|
+
path
|
|
8
|
+
}: AuthLogoutProps): Promise<NextResponse<unknown>>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { AuthLogout as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getDomain } from "./getDomain.js";
|
|
2
|
+
import { NextResponse } from "next/server.js";
|
|
3
|
+
//#region src/utils/auth/logout.ts
|
|
4
|
+
async function AuthLogout({ req, path }) {
|
|
5
|
+
const domain = getDomain(req);
|
|
6
|
+
const response = NextResponse.redirect(new URL(path || "/", domain));
|
|
7
|
+
[
|
|
8
|
+
"access_token",
|
|
9
|
+
"user_id",
|
|
10
|
+
"user_name",
|
|
11
|
+
"user_nickname",
|
|
12
|
+
"user_email",
|
|
13
|
+
"user_groups"
|
|
14
|
+
].forEach((cookieName) => {
|
|
15
|
+
response.cookies.delete(cookieName);
|
|
16
|
+
});
|
|
17
|
+
return response;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { AuthLogout as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NextResponse } from "next/server.js";
|
|
2
|
+
import { AuthTokenProps } from "uibee/utils";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/auth/token.d.ts
|
|
5
|
+
declare function AuthToken({
|
|
6
|
+
req,
|
|
7
|
+
redirectPath
|
|
8
|
+
}: AuthTokenProps): Promise<NextResponse<unknown>>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { AuthToken as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getDomain } from "./getDomain.js";
|
|
2
|
+
import { NextResponse } from "next/server.js";
|
|
3
|
+
//#region src/utils/auth/token.ts
|
|
4
|
+
async function AuthToken({ req, redirectPath }) {
|
|
5
|
+
const domain = getDomain(req);
|
|
6
|
+
const url = new URL(req.url);
|
|
7
|
+
const token = url.searchParams.get("access_token");
|
|
8
|
+
const btg = url.searchParams.get("btg");
|
|
9
|
+
const redirectCookie = req.cookies.get("redirect_after_login");
|
|
10
|
+
const redirect = redirectCookie ? redirectCookie.value : redirectPath || "/";
|
|
11
|
+
if (!token) return NextResponse.json({ error: "No access token provided" }, { status: 400 });
|
|
12
|
+
if (btg) return NextResponse.redirect(new URL(redirect, domain));
|
|
13
|
+
const accessToken = url.searchParams.get("access_token");
|
|
14
|
+
const userID = url.searchParams.get("id");
|
|
15
|
+
const username = url.searchParams.get("name");
|
|
16
|
+
const userNickname = url.searchParams.get("username");
|
|
17
|
+
const userEmail = url.searchParams.get("email");
|
|
18
|
+
const userGroups = url.searchParams.get("groups");
|
|
19
|
+
const response = NextResponse.redirect(new URL(redirect, domain));
|
|
20
|
+
response.cookies.set("access_token", accessToken);
|
|
21
|
+
response.cookies.set("user_id", userID);
|
|
22
|
+
response.cookies.set("user_name", username);
|
|
23
|
+
response.cookies.set("user_nickname", userNickname);
|
|
24
|
+
response.cookies.set("user_email", userEmail);
|
|
25
|
+
response.cookies.set("user_groups", userGroups);
|
|
26
|
+
if (redirectCookie) response.cookies.delete("redirect_after_login");
|
|
27
|
+
return response;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { AuthToken as default };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/utils/logoConsoleOutput/logoConsoleOutput.ts
|
|
2
|
+
function LogoConsoleOutput() {
|
|
3
|
+
const ua = navigator.userAgent;
|
|
4
|
+
if (!ua.includes("Chrome") && !ua.includes("Firefox") && !ua.includes("Safari")) {
|
|
5
|
+
console.log("Login - Linjeforeningen for IT");
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
console.log("%c███████╗ ███████╗\n██╔════╝ ╚════██║\n██║%c ██╗ ██████╗ ██████╗ ██╗███╗ ██╗ %c██║\n╚═╝%c ██║ ██╔═══██╗██╔════╝ ██║████╗ ██║ %c╚═╝%c\n ██║ ██║ ██║██║ ███╗██║██╔██╗ ██║\n ██║ ██║ ██║██║ ██║██║██║╚██╗██║\n%c██╗%c ██████╗╚██████╔╝╚██████╔╝██║██║ ╚████║ %c██╗\n██║%c ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ %c██║\n███████╗%c %c███████║\n╚══════╝ ╚══════╝%c\n\n - Laget av TekKom med 🍕 og ❤️", "color: #fd8738", "", "color: #fd8738", "", "color: #fd8738", "", "color: #fd8738", "", "color: #fd8738", "", "color: #fd8738", "", "color: #fd8738", "");
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { LogoConsoleOutput };
|
package/package.json
CHANGED
|
@@ -32,6 +32,41 @@ function t(s: BilingualString, lang: Lang): string {
|
|
|
32
32
|
return typeof s === 'string' ? s : s[lang]
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function Column({ col, lang }: { col: FooterColumn; lang: Lang }) {
|
|
36
|
+
return (
|
|
37
|
+
<div>
|
|
38
|
+
<h4 className='pb-2 text-sm font-medium tracking-widest text-login-100'>
|
|
39
|
+
{t(col.heading, lang)}
|
|
40
|
+
</h4>
|
|
41
|
+
{col.items.map((item, j) =>
|
|
42
|
+
item.href ? (
|
|
43
|
+
item.href.startsWith('/') ? (
|
|
44
|
+
<Link
|
|
45
|
+
key={j}
|
|
46
|
+
className='link--underscore-hover block text-login-50'
|
|
47
|
+
href={item.href}
|
|
48
|
+
>
|
|
49
|
+
{t(item.label, lang)}
|
|
50
|
+
</Link>
|
|
51
|
+
) : (
|
|
52
|
+
<a
|
|
53
|
+
key={j}
|
|
54
|
+
className='link--underscore-hover block text-login-50'
|
|
55
|
+
href={item.href}
|
|
56
|
+
>
|
|
57
|
+
{t(item.label, lang)}
|
|
58
|
+
</a>
|
|
59
|
+
)
|
|
60
|
+
) : (
|
|
61
|
+
<p key={j} className='text-login-50'>
|
|
62
|
+
{t(item.label, lang)}
|
|
63
|
+
</p>
|
|
64
|
+
)
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
35
70
|
export default function Footer({
|
|
36
71
|
logo,
|
|
37
72
|
sponsor,
|
|
@@ -43,15 +78,16 @@ export default function Footer({
|
|
|
43
78
|
className,
|
|
44
79
|
}: FooterProps) {
|
|
45
80
|
const year = new Date().getFullYear()
|
|
81
|
+
const [firstColumn, ...restColumns] = columns ?? []
|
|
46
82
|
const hasRight = (columns && columns.length > 0) || (socialLinks && socialLinks.length > 0)
|
|
47
83
|
|
|
48
84
|
return (
|
|
49
|
-
<div className={`mt-24 bg-login-950 md:mt-40 ${className || ''}`}>
|
|
85
|
+
<div className={`max-md:mt-24 bg-login-950 md:mt-40 ${className || ''}`}>
|
|
50
86
|
<div className={`
|
|
51
|
-
mx-auto w-full px-4 pt-16
|
|
87
|
+
mx-auto w-full pb-4 max-md:px-4 max-md:pt-16 md:max-w-304 md:px-12 md:pt-20
|
|
52
88
|
${hasRight ? 'md:grid md:grid-cols-[18rem_1fr] md:gap-x-12' : ''}
|
|
53
89
|
`}>
|
|
54
|
-
<div className='mx-auto grid w-full max-w-60 gap-16 md:row-span-2 md:max-w-72 md:gap-20'>
|
|
90
|
+
<div className='mx-auto grid w-full max-md:max-w-60 max-md:gap-16 md:row-span-2 md:max-w-72 md:gap-20'>
|
|
55
91
|
<div className='block w-full'>{logo}</div>
|
|
56
92
|
{sponsor && (
|
|
57
93
|
<div>
|
|
@@ -65,43 +101,26 @@ export default function Footer({
|
|
|
65
101
|
)}
|
|
66
102
|
</div>
|
|
67
103
|
|
|
68
|
-
{
|
|
104
|
+
{firstColumn && (
|
|
105
|
+
<div className='
|
|
106
|
+
grid w-full self-start max-md:mt-16
|
|
107
|
+
max-sm:max-w-60 sm:max-md:max-w-88
|
|
108
|
+
md:col-start-2 md:row-start-1 md:max-w-136 md:justify-self-center
|
|
109
|
+
'>
|
|
110
|
+
<Column col={firstColumn} lang={lang} />
|
|
111
|
+
</div>
|
|
112
|
+
)}
|
|
113
|
+
|
|
114
|
+
{restColumns.length > 0 && (
|
|
69
115
|
<div className={`
|
|
70
|
-
|
|
71
|
-
sm:max-w-88 sm:justify-items-end sm:justify-self-end
|
|
72
|
-
md:col-start-2 md:row-start-1 md:
|
|
73
|
-
${
|
|
116
|
+
grid w-full self-start max-md:mt-16 max-md:gap-8
|
|
117
|
+
max-sm:max-w-60 sm:max-md:max-w-88 sm:justify-items-end sm:justify-self-end
|
|
118
|
+
md:col-start-2 md:row-start-1 md:max-w-136 md:justify-self-end
|
|
119
|
+
${restColumns.length > 1 ? 'sm:grid-cols-2' : ''}
|
|
74
120
|
`}>
|
|
75
|
-
{
|
|
121
|
+
{restColumns.map((col, i) => (
|
|
76
122
|
<div key={i} className='sm:justify-self-center md:justify-self-end'>
|
|
77
|
-
<
|
|
78
|
-
{t(col.heading, lang)}
|
|
79
|
-
</h4>
|
|
80
|
-
{col.items.map((item, j) =>
|
|
81
|
-
item.href ? (
|
|
82
|
-
item.href.startsWith('/') ? (
|
|
83
|
-
<Link
|
|
84
|
-
key={j}
|
|
85
|
-
className='link--underscore-hover block text-login-100'
|
|
86
|
-
href={item.href}
|
|
87
|
-
>
|
|
88
|
-
{t(item.label, lang)}
|
|
89
|
-
</Link>
|
|
90
|
-
) : (
|
|
91
|
-
<a
|
|
92
|
-
key={j}
|
|
93
|
-
className='link--underscore-hover block text-login-100'
|
|
94
|
-
href={item.href}
|
|
95
|
-
>
|
|
96
|
-
{t(item.label, lang)}
|
|
97
|
-
</a>
|
|
98
|
-
)
|
|
99
|
-
) : (
|
|
100
|
-
<p key={j} className='text-login-100'>
|
|
101
|
-
{t(item.label, lang)}
|
|
102
|
-
</p>
|
|
103
|
-
)
|
|
104
|
-
)}
|
|
123
|
+
<Column col={col} lang={lang} />
|
|
105
124
|
</div>
|
|
106
125
|
))}
|
|
107
126
|
</div>
|
|
@@ -109,11 +128,12 @@ export default function Footer({
|
|
|
109
128
|
|
|
110
129
|
{socialLinks && socialLinks.length > 0 && (
|
|
111
130
|
<div className='md:col-start-2 md:row-start-2 md:justify-self-end'>
|
|
112
|
-
<div className='mx-auto mt-20 mb-12
|
|
131
|
+
<div className='mx-auto mt-20 mb-12 grid w-fit gap-6 max-sm:grid-cols-3 sm:grid-flow-col'>
|
|
113
132
|
{socialLinks.map((link, i) => (
|
|
114
133
|
<a
|
|
115
134
|
key={i}
|
|
116
|
-
className={`
|
|
135
|
+
className={`group mx-auto flex h-8 w-8 items-center justify-center
|
|
136
|
+
text-login-100 transition-all duration-200
|
|
117
137
|
${link.hoverClass ?? 'hover:text-login-50'}`}
|
|
118
138
|
title={link.title}
|
|
119
139
|
href={link.href}
|
|
@@ -127,9 +147,7 @@ export default function Footer({
|
|
|
127
147
|
</div>
|
|
128
148
|
)}
|
|
129
149
|
|
|
130
|
-
<div className='mt-
|
|
131
|
-
md:grid-cols-[auto_min-content] md:items-end md:gap-8'
|
|
132
|
-
>
|
|
150
|
+
<div className='mt-24 grid grid-cols-[auto_min-content] items-end gap-8 md:col-span-2 md:row-start-3'>
|
|
133
151
|
<p className='text-xs wrap-break-word text-login-100'>
|
|
134
152
|
{lang === 'no' ? 'Opphavsrett' : 'Copyright'} © {year} {t(copyright, lang)}
|
|
135
153
|
</p>
|
package/src/components/index.ts
CHANGED
package/src/globals.css
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
@config '../tailwind.config.ts';
|
|
4
4
|
|
|
5
|
+
/* Apply hover styles on :hover directly instead of gating them behind
|
|
6
|
+
@media (hover: hover), which never matches on devices reporting hover: none. */
|
|
7
|
+
@custom-variant hover (&:hover);
|
|
8
|
+
@custom-variant group-hover (&:is(:where(.group):hover *));
|
|
9
|
+
|
|
5
10
|
@theme {
|
|
6
11
|
--breakpoint-100px: 100px;
|
|
7
12
|
--breakpoint-200px: 200px;
|