uibee 2.17.5 → 3.0.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/README.md +34 -0
- package/dist/icons-lZYQ6Vlr.js +125 -0
- package/dist/src/components/index.d.ts +706 -30
- package/dist/src/components/index.js +3243 -44
- package/dist/src/hooks/index.d.ts +15 -3
- package/dist/src/hooks/index.js +44 -3
- package/dist/src/icons/index.d.ts +420 -0
- package/dist/src/icons/index.js +3 -0
- package/dist/src/styles/index.d.ts +1 -1
- package/dist/src/styles/index.js +2 -1
- package/dist/src/utils/index.d.ts +38 -5
- package/dist/src/utils/index.js +125 -6
- package/dist/{src/globals.css → style.css} +890 -678
- package/dist/useClickOutside-Cmp-RsP3.js +13 -0
- package/index.d.ts +0 -1
- package/package.json +22 -23
- package/src/components/alert/alert.tsx +20 -18
- package/src/components/buttons/button.tsx +28 -35
- package/src/components/confirm/confirmPopup.tsx +15 -17
- package/src/components/container/accordion.tsx +54 -0
- package/src/components/container/glassCard.tsx +14 -0
- package/src/components/container/iconBubble.tsx +30 -0
- package/src/components/container/leftBarPanel.tsx +15 -0
- package/src/components/container/pulseDot.tsx +31 -0
- package/src/components/container/statCard.tsx +24 -0
- package/src/components/container/tabs.tsx +64 -0
- package/src/components/footer/footer.tsx +124 -0
- package/src/components/footer/loginContent.tsx +70 -0
- package/src/components/index.ts +15 -0
- package/src/components/inputs/checkbox.tsx +4 -4
- package/src/components/inputs/input.tsx +11 -13
- package/src/components/inputs/multiSelect.tsx +144 -0
- package/src/components/inputs/radio.tsx +4 -4
- package/src/components/inputs/range.tsx +6 -5
- package/src/components/inputs/searchInput.tsx +1 -1
- package/src/components/inputs/select.tsx +19 -18
- package/src/components/inputs/shared/colorPickerPopup.tsx +5 -5
- package/src/components/inputs/shared/dateTimePickerPopup.tsx +9 -9
- package/src/components/inputs/shared/inputError.tsx +1 -1
- package/src/components/inputs/switch.tsx +7 -7
- package/src/components/inputs/tagInput.tsx +6 -7
- package/src/components/inputs/textarea.tsx +8 -10
- package/src/components/inputs/toggle.tsx +6 -6
- package/src/components/table/body.tsx +6 -6
- package/src/components/table/format.ts +1 -1
- package/src/components/table/header.tsx +1 -1
- package/src/components/table/pagination.tsx +17 -31
- package/src/components/table/table.tsx +2 -2
- package/src/components/version/version.tsx +1 -1
- package/src/components/vulnerability/constants.ts +6 -6
- package/src/components/vulnerability/severityPill.tsx +6 -7
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useClickOutside.ts +5 -22
- package/src/icons/icons.tsx +431 -0
- package/src/icons/index.ts +2 -0
- package/src/index.ts +0 -1
- package/src/types/hooks.d.ts +8 -2
- package/src/utils/index.ts +1 -1
- package/src/utils/logoConsoleOutput/logoConsoleOutput.ts +31 -0
- package/tsconfig.json +3 -2
- package/tsdown.config.ts +26 -0
- package/Readme.md +0 -29
- package/bun.lock +0 -662
- package/dist/src/components/alert/alert.d.ts +0 -8
- package/dist/src/components/alert/alert.js +0 -15
- package/dist/src/components/buttons/button.d.ts +0 -13
- package/dist/src/components/buttons/button.js +0 -30
- package/dist/src/components/confirm/confirmPopup.d.ts +0 -12
- package/dist/src/components/confirm/confirmPopup.js +0 -18
- package/dist/src/components/container/highlight.d.ts +0 -4
- package/dist/src/components/container/highlight.js +0 -4
- package/dist/src/components/container/page.d.ts +0 -8
- package/dist/src/components/container/page.js +0 -4
- package/dist/src/components/inputs/checkbox.d.ts +0 -17
- package/dist/src/components/inputs/checkbox.js +0 -37
- package/dist/src/components/inputs/input.d.ts +0 -12
- package/dist/src/components/inputs/input.js +0 -124
- package/dist/src/components/inputs/radio.d.ts +0 -17
- package/dist/src/components/inputs/radio.js +0 -27
- package/dist/src/components/inputs/range.d.ts +0 -11
- package/dist/src/components/inputs/range.js +0 -22
- package/dist/src/components/inputs/searchInput.d.ts +0 -6
- package/dist/src/components/inputs/searchInput.js +0 -42
- package/dist/src/components/inputs/select.d.ts +0 -23
- package/dist/src/components/inputs/select.js +0 -70
- package/dist/src/components/inputs/shared/colorPickerPopup.d.ts +0 -8
- package/dist/src/components/inputs/shared/colorPickerPopup.js +0 -191
- package/dist/src/components/inputs/shared/dateTimePickerPopup.d.ts +0 -9
- package/dist/src/components/inputs/shared/dateTimePickerPopup.js +0 -128
- package/dist/src/components/inputs/shared/fieldWrapper.d.ts +0 -14
- package/dist/src/components/inputs/shared/fieldWrapper.js +0 -8
- package/dist/src/components/inputs/shared/index.d.ts +0 -5
- package/dist/src/components/inputs/shared/index.js +0 -5
- package/dist/src/components/inputs/shared/inputError.d.ts +0 -6
- package/dist/src/components/inputs/shared/inputError.js +0 -6
- package/dist/src/components/inputs/shared/inputInfo.d.ts +0 -5
- package/dist/src/components/inputs/shared/inputInfo.js +0 -5
- package/dist/src/components/inputs/shared/inputLabel.d.ts +0 -9
- package/dist/src/components/inputs/shared/inputLabel.js +0 -4
- package/dist/src/components/inputs/switch.d.ts +0 -11
- package/dist/src/components/inputs/switch.js +0 -14
- package/dist/src/components/inputs/tagInput.d.ts +0 -15
- package/dist/src/components/inputs/tagInput.js +0 -40
- package/dist/src/components/inputs/textarea.d.ts +0 -11
- package/dist/src/components/inputs/textarea.js +0 -36
- package/dist/src/components/inputs/toggle.d.ts +0 -14
- package/dist/src/components/inputs/toggle.js +0 -12
- package/dist/src/components/login/loginPage.d.ts +0 -2
- package/dist/src/components/login/loginPage.js +0 -18
- package/dist/src/components/logo/logo.d.ts +0 -5
- package/dist/src/components/logo/logo.js +0 -6
- package/dist/src/components/logo/logoSmall.d.ts +0 -1
- package/dist/src/components/logo/logoSmall.js +0 -6
- package/dist/src/components/markdownrender/markdownRender.d.ts +0 -7
- package/dist/src/components/markdownrender/markdownRender.js +0 -26
- package/dist/src/components/navbar/bubble.d.ts +0 -14
- package/dist/src/components/navbar/bubble.js +0 -8
- package/dist/src/components/navbar/navbar.d.ts +0 -34
- package/dist/src/components/navbar/navbar.js +0 -36
- package/dist/src/components/navbar/navbarDropdown.d.ts +0 -7
- package/dist/src/components/navbar/navbarDropdown.js +0 -19
- package/dist/src/components/navbar/navbarItem.d.ts +0 -11
- package/dist/src/components/navbar/navbarItem.js +0 -12
- package/dist/src/components/table/body.d.ts +0 -15
- package/dist/src/components/table/body.js +0 -116
- package/dist/src/components/table/format.d.ts +0 -1
- package/dist/src/components/table/format.js +0 -27
- package/dist/src/components/table/header.d.ts +0 -8
- package/dist/src/components/table/header.js +0 -47
- package/dist/src/components/table/menu.d.ts +0 -17
- package/dist/src/components/table/menu.js +0 -30
- package/dist/src/components/table/pagination.d.ts +0 -6
- package/dist/src/components/table/pagination.js +0 -86
- package/dist/src/components/table/table.d.ts +0 -14
- package/dist/src/components/table/table.js +0 -14
- package/dist/src/components/toast/toastItem.d.ts +0 -2
- package/dist/src/components/toast/toastItem.js +0 -38
- package/dist/src/components/toast/toaster.d.ts +0 -9
- package/dist/src/components/toast/toaster.js +0 -86
- package/dist/src/components/toggle/language.d.ts +0 -4
- package/dist/src/components/toggle/language.js +0 -29
- package/dist/src/components/toggle/theme.d.ts +0 -3
- package/dist/src/components/toggle/theme.js +0 -30
- package/dist/src/components/version/version.d.ts +0 -7
- package/dist/src/components/version/version.js +0 -12
- package/dist/src/components/vulnerability/constants.d.ts +0 -4
- package/dist/src/components/vulnerability/constants.js +0 -14
- package/dist/src/components/vulnerability/severityPill.d.ts +0 -8
- package/dist/src/components/vulnerability/severityPill.js +0 -8
- package/dist/src/hooks/useClickOutside.d.ts +0 -2
- package/dist/src/hooks/useClickOutside.js +0 -27
- package/dist/src/hooks/useDarkMode.d.ts +0 -1
- package/dist/src/hooks/useDarkMode.js +0 -17
- package/dist/src/hooks/useVisibility.d.ts +0 -4
- package/dist/src/hooks/useVisibility.js +0 -23
- package/dist/src/index.d.ts +0 -5
- package/dist/src/index.js +0 -5
- package/dist/src/scripts/buildCss.d.ts +0 -1
- package/dist/src/scripts/buildCss.js +0 -22
- package/dist/src/scripts/index.d.ts +0 -1
- package/dist/src/scripts/index.js +0 -1
- package/dist/src/scripts/rewriteAlias.d.ts +0 -1
- package/dist/src/scripts/rewriteAlias.js +0 -31
- package/dist/src/utils/LogoConsoleOutput/LogoConsoleOutput.d.ts +0 -1
- package/dist/src/utils/LogoConsoleOutput/LogoConsoleOutput.js +0 -44
- package/dist/src/utils/auth/callback.d.ts +0 -2
- package/dist/src/utils/auth/callback.js +0 -63
- package/dist/src/utils/auth/getDomain.d.ts +0 -2
- package/dist/src/utils/auth/getDomain.js +0 -6
- package/dist/src/utils/auth/login.d.ts +0 -3
- package/dist/src/utils/auth/login.js +0 -14
- package/dist/src/utils/auth/logout.d.ts +0 -3
- package/dist/src/utils/auth/logout.js +0 -18
- package/dist/src/utils/auth/token.d.ts +0 -3
- package/dist/src/utils/auth/token.js +0 -33
- package/dist/tailwind.config.d.ts +0 -3
- package/dist/tailwind.config.js +0 -7
- package/src/scripts/buildCss.ts +0 -25
- package/src/scripts/index.ts +0 -1
- package/src/scripts/rewriteAlias.ts +0 -39
- package/src/utils/LogoConsoleOutput/LogoConsoleOutput.ts +0 -61
|
@@ -1,44 +1,3243 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as useClickOutside } from "../../useClickOutside-Cmp-RsP3.js";
|
|
3
|
+
import { D as Facebook, Kt as Wikijs, N as Github, W as Linkedin, x as Discord } from "../../icons-lZYQ6Vlr.js";
|
|
4
|
+
import React, { createContext, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { AlertCircle, AlertTriangle, ArrowUpRight, Calendar, Check, CheckCircle, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, CircleAlert, CircleHelp, Clock, EllipsisVertical, ExternalLink, Eye, Globe, Info, LogIn, LogOut, Pencil, Search, TriangleAlert, User, X } from "lucide-react";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import Markdown from "react-markdown";
|
|
8
|
+
import remarkGfm from "remark-gfm";
|
|
9
|
+
import rehypeHighlight from "rehype-highlight";
|
|
10
|
+
import { usePathname, useRouter, useSearchParams } from "next/navigation.js";
|
|
11
|
+
import Image from "next/image.js";
|
|
12
|
+
import { getCookie, setCookie } from "utilbee";
|
|
13
|
+
import Link from "next/link.js";
|
|
14
|
+
import { createPortal } from "react-dom";
|
|
15
|
+
//#region src/components/inputs/shared/inputLabel.tsx
|
|
16
|
+
function InputLabel({ label, name, required, disabled, className }) {
|
|
17
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
18
|
+
htmlFor: name,
|
|
19
|
+
className: `text-sm font-medium text-login-text ${disabled ? "opacity-50 cursor-not-allowed" : ""} ${className || ""}`,
|
|
20
|
+
title: label,
|
|
21
|
+
children: [
|
|
22
|
+
label,
|
|
23
|
+
" ",
|
|
24
|
+
required && /* @__PURE__ */ jsx("span", {
|
|
25
|
+
className: "text-red-500",
|
|
26
|
+
children: "*"
|
|
27
|
+
})
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/components/inputs/shared/inputInfo.tsx
|
|
33
|
+
function InputInfo({ info }) {
|
|
34
|
+
return /* @__PURE__ */ jsx("div", {
|
|
35
|
+
className: "text-login-200 hover:text-login-text transition-colors",
|
|
36
|
+
"aria-label": info,
|
|
37
|
+
title: info,
|
|
38
|
+
children: /* @__PURE__ */ jsx(CircleHelp, { className: "w-4 h-4" })
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/components/inputs/shared/inputError.tsx
|
|
43
|
+
function InputError({ error, id }) {
|
|
44
|
+
if (!error) return /* @__PURE__ */ jsx("div", { className: "h-4" });
|
|
45
|
+
return /* @__PURE__ */ jsx("div", {
|
|
46
|
+
className: "h-4",
|
|
47
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
48
|
+
id,
|
|
49
|
+
className: "text-xs text-red-400 ml-1 truncate block",
|
|
50
|
+
role: "alert",
|
|
51
|
+
title: error,
|
|
52
|
+
children: error
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/components/markdownrender/markdownRender.tsx
|
|
58
|
+
function makeDefaultComponents() {
|
|
59
|
+
return {
|
|
60
|
+
h1: ({ ...props }) => /* @__PURE__ */ jsx("h2", { ...props }),
|
|
61
|
+
input({ type, checked }) {
|
|
62
|
+
if (type !== "checkbox") return /* @__PURE__ */ jsx("input", { type });
|
|
63
|
+
return /* @__PURE__ */ jsx("span", {
|
|
64
|
+
"data-task-checkbox": true,
|
|
65
|
+
className: `inline-flex items-center justify-center w-4 h-4 rounded-xs border-2 shrink-0 align-middle
|
|
66
|
+
${checked ? "bg-login border-login" : "border-login/50"}`,
|
|
67
|
+
children: checked && /* @__PURE__ */ jsx("svg", {
|
|
68
|
+
viewBox: "0 0 10 8",
|
|
69
|
+
className: "w-2.5 h-2.5 fill-none stroke-white stroke-2",
|
|
70
|
+
children: /* @__PURE__ */ jsx("polyline", {
|
|
71
|
+
points: "1,4 4,7 9,1",
|
|
72
|
+
strokeLinecap: "round",
|
|
73
|
+
strokeLinejoin: "round"
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
a({ href, children }) {
|
|
79
|
+
return /* @__PURE__ */ jsxs("a", {
|
|
80
|
+
href,
|
|
81
|
+
target: "_blank",
|
|
82
|
+
rel: "noopener noreferrer",
|
|
83
|
+
className: "inline-flex items-center gap-1 text-login hover:text-login/80 underline underline-offset-2 transition-colors",
|
|
84
|
+
children: [children, /* @__PURE__ */ jsx(ExternalLink, { className: "w-3 h-3 shrink-0 opacity-70" })]
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
pre({ children }) {
|
|
88
|
+
return /* @__PURE__ */ jsx("pre", {
|
|
89
|
+
className: "block rounded-lg overflow-auto whitespace-pre-wrap wrap-break-word w-full",
|
|
90
|
+
children
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function MarkdownRender({ MDstr, components, className, size }) {
|
|
96
|
+
return /* @__PURE__ */ jsx("div", {
|
|
97
|
+
className: className ?? `prose ${size === "sm" ? "prose-sm" : size === "lg" ? "prose-lg" : size === "xl" ? "prose-xl" : ""} prose-custom max-w-none`,
|
|
98
|
+
children: /* @__PURE__ */ jsx(Markdown, {
|
|
99
|
+
components: {
|
|
100
|
+
...makeDefaultComponents(),
|
|
101
|
+
...components
|
|
102
|
+
},
|
|
103
|
+
remarkPlugins: [remarkGfm],
|
|
104
|
+
rehypePlugins: [rehypeHighlight],
|
|
105
|
+
children: MDstr.replace(/\\n/g, "\n")
|
|
106
|
+
})
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/components/inputs/shared/fieldWrapper.tsx
|
|
111
|
+
function FieldWrapper({ label, name, required, info, error, description, textSize = "sm", children, className }) {
|
|
112
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
113
|
+
className: `flex flex-col gap-1 w-full relative ${className || ""}`,
|
|
114
|
+
children: [
|
|
115
|
+
(label || info) && /* @__PURE__ */ jsxs("div", {
|
|
116
|
+
className: "flex items-center justify-between mb-1",
|
|
117
|
+
children: [label && /* @__PURE__ */ jsx(InputLabel, {
|
|
118
|
+
label,
|
|
119
|
+
name,
|
|
120
|
+
required,
|
|
121
|
+
className: `ml-1 ${textSize === "sm" ? "text-sm!" : "text-base!"}`
|
|
122
|
+
}), info && /* @__PURE__ */ jsx(InputInfo, { info })]
|
|
123
|
+
}),
|
|
124
|
+
description && /* @__PURE__ */ jsx("div", {
|
|
125
|
+
className: "text-login-100 **:text-xs! ml-1 mb-1",
|
|
126
|
+
children: /* @__PURE__ */ jsx(MarkdownRender, { MDstr: String(description || "") })
|
|
127
|
+
}),
|
|
128
|
+
children,
|
|
129
|
+
/* @__PURE__ */ jsx(InputError, {
|
|
130
|
+
error,
|
|
131
|
+
id: `${name}-error`
|
|
132
|
+
})
|
|
133
|
+
]
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
//#region src/components/inputs/shared/colorPickerPopup.tsx
|
|
138
|
+
function hexToHsv(hex) {
|
|
139
|
+
hex = hex.replace("#", "");
|
|
140
|
+
let r = 0, g = 0, b = 0;
|
|
141
|
+
if (hex.length === 3) {
|
|
142
|
+
r = parseInt(hex[0] + hex[0], 16);
|
|
143
|
+
g = parseInt(hex[1] + hex[1], 16);
|
|
144
|
+
b = parseInt(hex[2] + hex[2], 16);
|
|
145
|
+
} else if (hex.length === 6) {
|
|
146
|
+
r = parseInt(hex.substring(0, 2), 16);
|
|
147
|
+
g = parseInt(hex.substring(2, 4), 16);
|
|
148
|
+
b = parseInt(hex.substring(4, 6), 16);
|
|
149
|
+
}
|
|
150
|
+
r /= 255;
|
|
151
|
+
g /= 255;
|
|
152
|
+
b /= 255;
|
|
153
|
+
const max = Math.max(r, g, b);
|
|
154
|
+
const min = Math.min(r, g, b);
|
|
155
|
+
const d = max - min;
|
|
156
|
+
let h = 0;
|
|
157
|
+
const s = max === 0 ? 0 : d / max;
|
|
158
|
+
const v = max;
|
|
159
|
+
if (max !== min) {
|
|
160
|
+
switch (max) {
|
|
161
|
+
case r:
|
|
162
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
163
|
+
break;
|
|
164
|
+
case g:
|
|
165
|
+
h = (b - r) / d + 2;
|
|
166
|
+
break;
|
|
167
|
+
case b:
|
|
168
|
+
h = (r - g) / d + 4;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
h /= 6;
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
h: h * 360,
|
|
175
|
+
s: s * 100,
|
|
176
|
+
v: v * 100
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function hsvToRgb(h, s, v) {
|
|
180
|
+
let r = 0, g = 0, b = 0;
|
|
181
|
+
const i = Math.floor(h * 6);
|
|
182
|
+
const f = h * 6 - i;
|
|
183
|
+
const p = v * (1 - s);
|
|
184
|
+
const q = v * (1 - f * s);
|
|
185
|
+
const t = v * (1 - (1 - f) * s);
|
|
186
|
+
switch (i % 6) {
|
|
187
|
+
case 0:
|
|
188
|
+
r = v;
|
|
189
|
+
g = t;
|
|
190
|
+
b = p;
|
|
191
|
+
break;
|
|
192
|
+
case 1:
|
|
193
|
+
r = q;
|
|
194
|
+
g = v;
|
|
195
|
+
b = p;
|
|
196
|
+
break;
|
|
197
|
+
case 2:
|
|
198
|
+
r = p;
|
|
199
|
+
g = v;
|
|
200
|
+
b = t;
|
|
201
|
+
break;
|
|
202
|
+
case 3:
|
|
203
|
+
r = p;
|
|
204
|
+
g = q;
|
|
205
|
+
b = v;
|
|
206
|
+
break;
|
|
207
|
+
case 4:
|
|
208
|
+
r = t;
|
|
209
|
+
g = p;
|
|
210
|
+
b = v;
|
|
211
|
+
break;
|
|
212
|
+
case 5:
|
|
213
|
+
r = v;
|
|
214
|
+
g = p;
|
|
215
|
+
b = q;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
r: Math.round(r * 255),
|
|
220
|
+
g: Math.round(g * 255),
|
|
221
|
+
b: Math.round(b * 255)
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function hsvToHex(h, s, v) {
|
|
225
|
+
const { r, g, b } = hsvToRgb(h / 360, s / 100, v / 100);
|
|
226
|
+
function toHex(x) {
|
|
227
|
+
const hex = x.toString(16);
|
|
228
|
+
return hex.length === 1 ? "0" + hex : hex;
|
|
229
|
+
}
|
|
230
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
231
|
+
}
|
|
232
|
+
const PRESET_COLORS = [
|
|
233
|
+
"#f87171",
|
|
234
|
+
"#fd8738",
|
|
235
|
+
"#fbbf24",
|
|
236
|
+
"#facc15",
|
|
237
|
+
"#a3e635",
|
|
238
|
+
"#4ade80",
|
|
239
|
+
"#34d399",
|
|
240
|
+
"#2dd4bf",
|
|
241
|
+
"#38bdf8",
|
|
242
|
+
"#60a5fa",
|
|
243
|
+
"#818cf8",
|
|
244
|
+
"#a78bfa",
|
|
245
|
+
"#c084fc",
|
|
246
|
+
"#e879f9",
|
|
247
|
+
"#f472b6",
|
|
248
|
+
"#fb7185"
|
|
249
|
+
];
|
|
250
|
+
function SaturationPicker({ hsv, onChange }) {
|
|
251
|
+
const containerRef = useRef(null);
|
|
252
|
+
function handleMove(e) {
|
|
253
|
+
if (!containerRef.current) return;
|
|
254
|
+
const { left, top, width, height } = containerRef.current.getBoundingClientRect();
|
|
255
|
+
const x = Math.min(Math.max((e.clientX - left) / width, 0), 1);
|
|
256
|
+
const y = Math.min(Math.max((e.clientY - top) / height, 0), 1);
|
|
257
|
+
onChange(x * 100, (1 - y) * 100);
|
|
258
|
+
}
|
|
259
|
+
function handleMouseDown(e) {
|
|
260
|
+
handleMove(e);
|
|
261
|
+
function moveHandler(e) {
|
|
262
|
+
handleMove(e);
|
|
263
|
+
}
|
|
264
|
+
function upHandler() {
|
|
265
|
+
window.removeEventListener("mousemove", moveHandler);
|
|
266
|
+
window.removeEventListener("mouseup", upHandler);
|
|
267
|
+
}
|
|
268
|
+
window.addEventListener("mousemove", moveHandler);
|
|
269
|
+
window.addEventListener("mouseup", upHandler);
|
|
270
|
+
}
|
|
271
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
272
|
+
ref: containerRef,
|
|
273
|
+
className: "w-full h-32 relative rounded-md overflow-hidden cursor-crosshair mb-3 select-none",
|
|
274
|
+
style: { backgroundColor: hsvToHex(hsv.h, 100, 100) },
|
|
275
|
+
onMouseDown: handleMouseDown,
|
|
276
|
+
children: [
|
|
277
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-linear-to-r from-white to-transparent" }),
|
|
278
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-linear-to-t from-black to-transparent" }),
|
|
279
|
+
/* @__PURE__ */ jsx("div", {
|
|
280
|
+
className: `
|
|
281
|
+
absolute w-3 h-3 border-2 border-white rounded-full
|
|
282
|
+
shadow-md -translate-x-1/2 -translate-y-1/2 pointer-events-none
|
|
283
|
+
`,
|
|
284
|
+
style: {
|
|
285
|
+
left: `${hsv.s}%`,
|
|
286
|
+
top: `${100 - hsv.v}%`
|
|
287
|
+
}
|
|
288
|
+
})
|
|
289
|
+
]
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
function HuePicker({ hue, onChange }) {
|
|
293
|
+
const containerRef = useRef(null);
|
|
294
|
+
function handleMove(e) {
|
|
295
|
+
if (!containerRef.current) return;
|
|
296
|
+
const { left, width } = containerRef.current.getBoundingClientRect();
|
|
297
|
+
onChange(Math.min(Math.max((e.clientX - left) / width, 0), 1) * 360);
|
|
298
|
+
}
|
|
299
|
+
function handleMouseDown(e) {
|
|
300
|
+
handleMove(e);
|
|
301
|
+
function moveHandler(e) {
|
|
302
|
+
handleMove(e);
|
|
303
|
+
}
|
|
304
|
+
function upHandler() {
|
|
305
|
+
window.removeEventListener("mousemove", moveHandler);
|
|
306
|
+
window.removeEventListener("mouseup", upHandler);
|
|
307
|
+
}
|
|
308
|
+
window.addEventListener("mousemove", moveHandler);
|
|
309
|
+
window.addEventListener("mouseup", upHandler);
|
|
310
|
+
}
|
|
311
|
+
return /* @__PURE__ */ jsx("div", {
|
|
312
|
+
ref: containerRef,
|
|
313
|
+
className: "w-full h-3 relative rounded-full cursor-pointer mb-4 select-none",
|
|
314
|
+
style: { background: "linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%)" },
|
|
315
|
+
onMouseDown: handleMouseDown,
|
|
316
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
317
|
+
className: `
|
|
318
|
+
absolute w-4 h-4 bg-white border border-gray-200
|
|
319
|
+
rounded-full shadow-sm -translate-x-1/2 -translate-y-1/2
|
|
320
|
+
top-1/2 pointer-events-none
|
|
321
|
+
`,
|
|
322
|
+
style: { left: `${hue / 360 * 100}%` }
|
|
323
|
+
})
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
function ColorPickerPopup({ value, onChange, onClose, anchorName }) {
|
|
327
|
+
const [hsv, setHsv] = useState(() => hexToHsv(value || "#000000"));
|
|
328
|
+
const [hexInput, setHexInput] = useState(value || "#000000");
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
if (value && value !== hexInput) {
|
|
331
|
+
setHsv(hexToHsv(value));
|
|
332
|
+
setHexInput(value);
|
|
333
|
+
}
|
|
334
|
+
}, [value]);
|
|
335
|
+
function handleColorChange(newHsv) {
|
|
336
|
+
setHsv(newHsv);
|
|
337
|
+
const hex = hsvToHex(newHsv.h, newHsv.s, newHsv.v);
|
|
338
|
+
setHexInput(hex);
|
|
339
|
+
onChange(hex);
|
|
340
|
+
}
|
|
341
|
+
function handleSaturationChange(s, v) {
|
|
342
|
+
handleColorChange({
|
|
343
|
+
...hsv,
|
|
344
|
+
s,
|
|
345
|
+
v
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
function handleHueChange(h) {
|
|
349
|
+
handleColorChange({
|
|
350
|
+
...hsv,
|
|
351
|
+
h
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
function manualHexChange(e) {
|
|
355
|
+
const val = e.target.value;
|
|
356
|
+
setHexInput(val);
|
|
357
|
+
if (/^#[0-9A-F]{6}$/i.test(val)) {
|
|
358
|
+
setHsv(hexToHsv(val));
|
|
359
|
+
onChange(val);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
363
|
+
className: "fixed z-50 bg-login-700 border border-login-500/50 rounded-md shadow-xl p-3 w-64 select-none anchor-popup",
|
|
364
|
+
style: {
|
|
365
|
+
positionAnchor: anchorName,
|
|
366
|
+
positionArea: "bottom span-right",
|
|
367
|
+
insetArea: "bottom span-right",
|
|
368
|
+
positionTryFallbacks: "flip-block",
|
|
369
|
+
margin: "0.25rem 0"
|
|
370
|
+
},
|
|
371
|
+
children: [
|
|
372
|
+
/* @__PURE__ */ jsx(SaturationPicker, {
|
|
373
|
+
hsv,
|
|
374
|
+
onChange: handleSaturationChange
|
|
375
|
+
}),
|
|
376
|
+
/* @__PURE__ */ jsx(HuePicker, {
|
|
377
|
+
hue: hsv.h,
|
|
378
|
+
onChange: handleHueChange
|
|
379
|
+
}),
|
|
380
|
+
/* @__PURE__ */ jsxs("div", {
|
|
381
|
+
className: "flex items-center gap-2 mb-3",
|
|
382
|
+
children: [
|
|
383
|
+
/* @__PURE__ */ jsx("div", {
|
|
384
|
+
className: "text-xs text-login-200 font-mono",
|
|
385
|
+
children: "HEX"
|
|
386
|
+
}),
|
|
387
|
+
/* @__PURE__ */ jsx("input", {
|
|
388
|
+
type: "text",
|
|
389
|
+
value: hexInput,
|
|
390
|
+
onChange: manualHexChange,
|
|
391
|
+
className: `
|
|
392
|
+
flex-1 min-w-0 bg-login-600 border border-login-500/50 rounded
|
|
393
|
+
px-2 py-1 text-sm text-login-text focus:outline-none
|
|
394
|
+
focus:border-login/60 focus:ring-1 focus:ring-login/30
|
|
395
|
+
`,
|
|
396
|
+
spellCheck: false
|
|
397
|
+
}),
|
|
398
|
+
/* @__PURE__ */ jsx("div", {
|
|
399
|
+
className: "w-8 h-8 rounded border border-login-500/50 shrink-0",
|
|
400
|
+
style: { backgroundColor: hexInput }
|
|
401
|
+
})
|
|
402
|
+
]
|
|
403
|
+
}),
|
|
404
|
+
/* @__PURE__ */ jsx("div", {
|
|
405
|
+
className: "grid grid-cols-8 gap-1.5 pt-3 border-t border-login-500/25",
|
|
406
|
+
children: PRESET_COLORS.map((color) => /* @__PURE__ */ jsx("button", {
|
|
407
|
+
type: "button",
|
|
408
|
+
className: `
|
|
409
|
+
w-6 h-6 rounded-sm cursor-pointer hover:scale-110
|
|
410
|
+
hover:zIndex-10 transition-transform ring-1 ring-inset ring-black/10
|
|
411
|
+
`,
|
|
412
|
+
style: { backgroundColor: color },
|
|
413
|
+
onClick: () => {
|
|
414
|
+
setHsv(hexToHsv(color));
|
|
415
|
+
setHexInput(color);
|
|
416
|
+
onChange(color);
|
|
417
|
+
onClose();
|
|
418
|
+
},
|
|
419
|
+
title: color
|
|
420
|
+
}, color))
|
|
421
|
+
})
|
|
422
|
+
]
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
//#endregion
|
|
426
|
+
//#region src/components/inputs/shared/dateTimePickerPopup.tsx
|
|
427
|
+
const DAYS = [
|
|
428
|
+
"Mo",
|
|
429
|
+
"Tu",
|
|
430
|
+
"We",
|
|
431
|
+
"Th",
|
|
432
|
+
"Fr",
|
|
433
|
+
"Sa",
|
|
434
|
+
"Su"
|
|
435
|
+
];
|
|
436
|
+
const MONTHS = [
|
|
437
|
+
"January",
|
|
438
|
+
"February",
|
|
439
|
+
"March",
|
|
440
|
+
"April",
|
|
441
|
+
"May",
|
|
442
|
+
"June",
|
|
443
|
+
"July",
|
|
444
|
+
"August",
|
|
445
|
+
"September",
|
|
446
|
+
"October",
|
|
447
|
+
"November",
|
|
448
|
+
"December"
|
|
449
|
+
];
|
|
450
|
+
function DateTimePickerPopup({ value, onChange, type, onClose, anchorName }) {
|
|
451
|
+
const [currentDate, setCurrentDate] = useState(/* @__PURE__ */ new Date());
|
|
452
|
+
const [timeInput, setTimeInput] = useState({
|
|
453
|
+
hours: value ? value.getHours().toString() : "0",
|
|
454
|
+
minutes: value ? value.getMinutes().toString() : "0"
|
|
455
|
+
});
|
|
456
|
+
useEffect(() => {
|
|
457
|
+
if (value) {
|
|
458
|
+
setCurrentDate(value);
|
|
459
|
+
setTimeInput((prev) => ({
|
|
460
|
+
hours: prev.hours === "" && value.getHours() === 0 ? "" : value.getHours().toString(),
|
|
461
|
+
minutes: prev.minutes === "" && value.getMinutes() === 0 ? "" : value.getMinutes().toString()
|
|
462
|
+
}));
|
|
463
|
+
}
|
|
464
|
+
}, [value]);
|
|
465
|
+
function handleDateSelect(day) {
|
|
466
|
+
const newDate = new Date(currentDate);
|
|
467
|
+
newDate.setDate(day);
|
|
468
|
+
if (value) {
|
|
469
|
+
newDate.setHours(value.getHours());
|
|
470
|
+
newDate.setMinutes(value.getMinutes());
|
|
471
|
+
} else newDate.setHours(0, 0, 0, 0);
|
|
472
|
+
onChange(newDate);
|
|
473
|
+
if (type === "date" && onClose) onClose();
|
|
474
|
+
}
|
|
475
|
+
function handleTimeChange(timeUnit, val) {
|
|
476
|
+
const newDate = value ? new Date(value) : /* @__PURE__ */ new Date();
|
|
477
|
+
if (!value) newDate.setHours(0, 0, 0, 0);
|
|
478
|
+
if (timeUnit === "hours") {
|
|
479
|
+
if (val < 0 || val > 23) return;
|
|
480
|
+
newDate.setHours(val);
|
|
481
|
+
}
|
|
482
|
+
if (timeUnit === "minutes") {
|
|
483
|
+
if (val < 0 || val > 59) return;
|
|
484
|
+
newDate.setMinutes(val);
|
|
485
|
+
}
|
|
486
|
+
onChange(newDate);
|
|
487
|
+
}
|
|
488
|
+
function onTimeInputChange(unit, val) {
|
|
489
|
+
if (val === "") {
|
|
490
|
+
setTimeInput((prev) => ({
|
|
491
|
+
...prev,
|
|
492
|
+
[unit]: ""
|
|
493
|
+
}));
|
|
494
|
+
handleTimeChange(unit, 0);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (!/^\d+$/.test(val)) return;
|
|
498
|
+
const num = parseInt(val);
|
|
499
|
+
if (unit === "hours" && num > 23) return;
|
|
500
|
+
if (unit === "minutes" && num > 59) return;
|
|
501
|
+
setTimeInput((prev) => ({
|
|
502
|
+
...prev,
|
|
503
|
+
[unit]: val
|
|
504
|
+
}));
|
|
505
|
+
handleTimeChange(unit, num);
|
|
506
|
+
}
|
|
507
|
+
function onTimeInputBlur(unit) {
|
|
508
|
+
if (timeInput[unit] === "") {
|
|
509
|
+
const num = unit === "hours" ? value?.getHours() ?? 0 : value?.getMinutes() ?? 0;
|
|
510
|
+
setTimeInput((prev) => ({
|
|
511
|
+
...prev,
|
|
512
|
+
[unit]: num.toString()
|
|
513
|
+
}));
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
function getDaysInMonth(year, month) {
|
|
517
|
+
return new Date(year, month + 1, 0).getDate();
|
|
518
|
+
}
|
|
519
|
+
function getFirstDayOfMonth(year, month) {
|
|
520
|
+
return new Date(year, month, 1).getDay();
|
|
521
|
+
}
|
|
522
|
+
function renderCalendar() {
|
|
523
|
+
const year = currentDate.getFullYear();
|
|
524
|
+
const month = currentDate.getMonth();
|
|
525
|
+
const daysInMonth = getDaysInMonth(year, month);
|
|
526
|
+
const firstDay = getFirstDayOfMonth(year, month);
|
|
527
|
+
const days = [];
|
|
528
|
+
const adjustedFirstDay = firstDay === 0 ? 6 : firstDay - 1;
|
|
529
|
+
for (let i = 0; i < adjustedFirstDay; i++) days.push(/* @__PURE__ */ jsx("div", { className: "w-8 h-8" }, `empty-${i}`));
|
|
530
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
531
|
+
const isSelected = value && value.getDate() === i && value.getMonth() === month && value.getFullYear() === year;
|
|
532
|
+
const isToday = (/* @__PURE__ */ new Date()).getDate() === i && (/* @__PURE__ */ new Date()).getMonth() === month && (/* @__PURE__ */ new Date()).getFullYear() === year;
|
|
533
|
+
days.push(/* @__PURE__ */ jsx("button", {
|
|
534
|
+
type: "button",
|
|
535
|
+
onClick: () => handleDateSelect(i),
|
|
536
|
+
className: `
|
|
537
|
+
w-8 h-8 flex items-center justify-center rounded-full text-sm
|
|
538
|
+
hover:bg-login-600 transition-colors
|
|
539
|
+
${isSelected ? "bg-login! text-white! hover:bg-login!" : ""}
|
|
540
|
+
${!isSelected && isToday ? "text-login! font-bold" : ""}
|
|
541
|
+
${!isSelected && !isToday ? "text-login-text!" : ""}
|
|
542
|
+
`,
|
|
543
|
+
children: i
|
|
544
|
+
}, i));
|
|
545
|
+
}
|
|
546
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
547
|
+
className: "p-2",
|
|
548
|
+
children: [
|
|
549
|
+
/* @__PURE__ */ jsxs("div", {
|
|
550
|
+
className: "flex items-center justify-between mb-2",
|
|
551
|
+
children: [
|
|
552
|
+
/* @__PURE__ */ jsx("button", {
|
|
553
|
+
type: "button",
|
|
554
|
+
onClick: () => setCurrentDate(new Date(year, month - 1)),
|
|
555
|
+
className: "p-1 hover:bg-login-600 rounded-full text-login-text transition-colors",
|
|
556
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4" })
|
|
557
|
+
}),
|
|
558
|
+
/* @__PURE__ */ jsxs("span", {
|
|
559
|
+
className: "font-medium text-login-text",
|
|
560
|
+
children: [
|
|
561
|
+
MONTHS[month],
|
|
562
|
+
" ",
|
|
563
|
+
year
|
|
564
|
+
]
|
|
565
|
+
}),
|
|
566
|
+
/* @__PURE__ */ jsx("button", {
|
|
567
|
+
type: "button",
|
|
568
|
+
onClick: () => setCurrentDate(new Date(year, month + 1)),
|
|
569
|
+
className: "p-1 hover:bg-login-600 rounded-full text-login-text transition-colors",
|
|
570
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4" })
|
|
571
|
+
})
|
|
572
|
+
]
|
|
573
|
+
}),
|
|
574
|
+
/* @__PURE__ */ jsx("div", {
|
|
575
|
+
className: "grid grid-cols-7 gap-1 mb-1",
|
|
576
|
+
children: DAYS.map((d) => /* @__PURE__ */ jsx("div", {
|
|
577
|
+
className: "w-8 text-center text-xs text-login-200 font-medium",
|
|
578
|
+
children: d
|
|
579
|
+
}, d))
|
|
580
|
+
}),
|
|
581
|
+
/* @__PURE__ */ jsx("div", {
|
|
582
|
+
className: "grid grid-cols-7 gap-1",
|
|
583
|
+
children: days
|
|
584
|
+
})
|
|
585
|
+
]
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
function renderTimePicker() {
|
|
589
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
590
|
+
className: "p-2 border-t border-login-500/25 flex justify-center gap-2",
|
|
591
|
+
children: [
|
|
592
|
+
/* @__PURE__ */ jsxs("div", {
|
|
593
|
+
className: "flex flex-col items-center",
|
|
594
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
595
|
+
className: "text-xs text-login-200 mb-1",
|
|
596
|
+
children: "Hour"
|
|
597
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
598
|
+
type: "text",
|
|
599
|
+
inputMode: "numeric",
|
|
600
|
+
value: timeInput.hours,
|
|
601
|
+
onChange: (e) => onTimeInputChange("hours", e.target.value),
|
|
602
|
+
onBlur: () => onTimeInputBlur("hours"),
|
|
603
|
+
className: `
|
|
604
|
+
w-16 p-1 bg-login-600 rounded text-center text-login-text text-sm
|
|
605
|
+
border border-login-500/50 focus:border-login/60 focus:ring-1 focus:ring-login/30 outline-none
|
|
606
|
+
`
|
|
607
|
+
})]
|
|
608
|
+
}),
|
|
609
|
+
/* @__PURE__ */ jsx("div", {
|
|
610
|
+
className: "flex items-end pb-2 text-login-text",
|
|
611
|
+
children: ":"
|
|
612
|
+
}),
|
|
613
|
+
/* @__PURE__ */ jsxs("div", {
|
|
614
|
+
className: "flex flex-col items-center",
|
|
615
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
616
|
+
className: "text-xs text-login-200 mb-1",
|
|
617
|
+
children: "Minute"
|
|
618
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
619
|
+
type: "text",
|
|
620
|
+
inputMode: "numeric",
|
|
621
|
+
value: timeInput.minutes,
|
|
622
|
+
onChange: (e) => onTimeInputChange("minutes", e.target.value),
|
|
623
|
+
onBlur: () => onTimeInputBlur("minutes"),
|
|
624
|
+
className: `
|
|
625
|
+
w-16 p-1 bg-login-600 rounded text-center text-login-text text-sm
|
|
626
|
+
border border-login-500/50 focus:border-login/60 focus:ring-1 focus:ring-login/30 outline-none
|
|
627
|
+
`
|
|
628
|
+
})]
|
|
629
|
+
})
|
|
630
|
+
]
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
634
|
+
className: "fixed z-50 bg-login-700 border border-login-500/50 rounded-md shadow-xl p-1 min-w-70 anchor-popup",
|
|
635
|
+
style: {
|
|
636
|
+
positionAnchor: anchorName,
|
|
637
|
+
positionArea: "bottom span-right",
|
|
638
|
+
insetArea: "bottom span-right",
|
|
639
|
+
positionTryFallbacks: "flip-block",
|
|
640
|
+
margin: "0.25rem 0"
|
|
641
|
+
},
|
|
642
|
+
children: [type !== "time" && renderCalendar(), (type === "time" || type === "datetime-local") && renderTimePicker()]
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
//#endregion
|
|
646
|
+
//#region src/components/inputs/input.tsx
|
|
647
|
+
function Input(props) {
|
|
648
|
+
const { name, label, error, className, icon, info, description, textSize = "sm", ...inputProps } = props;
|
|
649
|
+
const { type = "text", value } = inputProps;
|
|
650
|
+
const localRef = useRef(null);
|
|
651
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
652
|
+
const anchorName = `--input-${useId().replace(/:/g, "")}`;
|
|
653
|
+
const containerRef = useRef(null);
|
|
654
|
+
useClickOutside(containerRef, () => setIsOpen(false));
|
|
655
|
+
const isDateType = [
|
|
656
|
+
"date",
|
|
657
|
+
"datetime-local",
|
|
658
|
+
"time"
|
|
659
|
+
].includes(type);
|
|
660
|
+
const isColorType = type === "color";
|
|
661
|
+
const isClickableType = isDateType || isColorType;
|
|
662
|
+
function handleIconClick() {
|
|
663
|
+
if (isClickableType && !inputProps.disabled) setIsOpen(!isOpen);
|
|
664
|
+
else if (localRef.current && !inputProps.disabled) localRef.current.focus();
|
|
665
|
+
}
|
|
666
|
+
function pad(n) {
|
|
667
|
+
return n.toString().padStart(2, "0");
|
|
668
|
+
}
|
|
669
|
+
function handleDateChange(date) {
|
|
670
|
+
const onChange = inputProps.onChange;
|
|
671
|
+
if (!onChange) return;
|
|
672
|
+
const yyyy = date.getFullYear();
|
|
673
|
+
const MM = pad(date.getMonth() + 1);
|
|
674
|
+
const dd = pad(date.getDate());
|
|
675
|
+
const hh = pad(date.getHours());
|
|
676
|
+
const mm = pad(date.getMinutes());
|
|
677
|
+
let newValue = "";
|
|
678
|
+
if (type === "date") newValue = `${yyyy}-${MM}-${dd}`;
|
|
679
|
+
else if (type === "time") newValue = `${hh}:${mm}`;
|
|
680
|
+
else if (type === "datetime-local") newValue = `${yyyy}-${MM}-${dd}T${hh}:${mm}`;
|
|
681
|
+
onChange({ target: {
|
|
682
|
+
name,
|
|
683
|
+
value: newValue,
|
|
684
|
+
type
|
|
685
|
+
} });
|
|
686
|
+
}
|
|
687
|
+
function handleColorChange(color) {
|
|
688
|
+
const onChange = inputProps.onChange;
|
|
689
|
+
if (!onChange) return;
|
|
690
|
+
onChange({ target: {
|
|
691
|
+
name,
|
|
692
|
+
value: color,
|
|
693
|
+
type
|
|
694
|
+
} });
|
|
695
|
+
}
|
|
696
|
+
let displayIcon = icon;
|
|
697
|
+
if (!displayIcon && isDateType) if (type === "time") displayIcon = /* @__PURE__ */ jsx(Clock, { className: "w-4 h-4" });
|
|
698
|
+
else displayIcon = /* @__PURE__ */ jsx(Calendar, { className: "w-4 h-4" });
|
|
699
|
+
else if (!displayIcon && isColorType) displayIcon = /* @__PURE__ */ jsx("div", {
|
|
700
|
+
className: "w-4 h-4 rounded border border-login-200",
|
|
701
|
+
style: { backgroundColor: value || "#000000" }
|
|
702
|
+
});
|
|
703
|
+
function getDateValue() {
|
|
704
|
+
if (!value) return null;
|
|
705
|
+
if (type === "time") {
|
|
706
|
+
const date = /* @__PURE__ */ new Date(`2000-01-01T${value}`);
|
|
707
|
+
return isNaN(date.getTime()) ? null : date;
|
|
708
|
+
}
|
|
709
|
+
const date = new Date(value);
|
|
710
|
+
return isNaN(date.getTime()) ? null : date;
|
|
711
|
+
}
|
|
712
|
+
function getDateDisplayValue() {
|
|
713
|
+
if (!value || !isDateType) return value;
|
|
714
|
+
const date = getDateValue();
|
|
715
|
+
if (!date) return value;
|
|
716
|
+
const yyyy = date.getFullYear();
|
|
717
|
+
const MM = pad(date.getMonth() + 1);
|
|
718
|
+
const dd = pad(date.getDate());
|
|
719
|
+
const hh = pad(date.getHours());
|
|
720
|
+
const mm = pad(date.getMinutes());
|
|
721
|
+
if (type === "date") return `${dd}.${MM}.${yyyy}`;
|
|
722
|
+
if (type === "time") return `${hh}:${mm}`;
|
|
723
|
+
if (type === "datetime-local") return `${dd}.${MM}.${yyyy} ${hh}:${mm}`;
|
|
724
|
+
return value;
|
|
725
|
+
}
|
|
726
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
727
|
+
label,
|
|
728
|
+
name,
|
|
729
|
+
required: inputProps.required,
|
|
730
|
+
info,
|
|
731
|
+
error,
|
|
732
|
+
description,
|
|
733
|
+
textSize,
|
|
734
|
+
className,
|
|
735
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
736
|
+
className: "relative flex items-center",
|
|
737
|
+
ref: containerRef,
|
|
738
|
+
children: [
|
|
739
|
+
displayIcon && /* @__PURE__ */ jsx("div", {
|
|
740
|
+
className: `
|
|
741
|
+
absolute left-3 text-login-200
|
|
742
|
+
${isClickableType && !inputProps.disabled ? "cursor-pointer hover:text-login-text" : "pointer-events-none"}
|
|
743
|
+
`,
|
|
744
|
+
onClick: handleIconClick,
|
|
745
|
+
children: displayIcon
|
|
746
|
+
}),
|
|
747
|
+
/* @__PURE__ */ jsx("input", {
|
|
748
|
+
...inputProps,
|
|
749
|
+
ref: localRef,
|
|
750
|
+
id: name,
|
|
751
|
+
name: isClickableType ? void 0 : name,
|
|
752
|
+
type: isClickableType ? "text" : type,
|
|
753
|
+
value: isDateType ? getDateDisplayValue() : value,
|
|
754
|
+
readOnly: isClickableType,
|
|
755
|
+
onClick: () => isClickableType && !inputProps.disabled && setIsOpen(true),
|
|
756
|
+
"aria-describedby": error ? `${name}-error` : void 0,
|
|
757
|
+
style: { anchorName },
|
|
758
|
+
className: `
|
|
759
|
+
w-full rounded-md bg-login-500/50 border border-login-500
|
|
760
|
+
text-login-text placeholder-login-200 text-sm
|
|
761
|
+
focus:outline-none focus:border-login/60 focus:ring-1 focus:ring-login/30
|
|
762
|
+
disabled:opacity-40 disabled:cursor-not-allowed
|
|
763
|
+
h-10 py-2 ${displayIcon ? "pl-10 pr-3" : "px-3"}
|
|
764
|
+
transition-all duration-150
|
|
765
|
+
input-reset
|
|
766
|
+
${error ? "border-red-500/70 focus:border-red-500/70 focus:ring-red-500/30" : ""}
|
|
767
|
+
${isClickableType && !inputProps.disabled ? "cursor-pointer" : ""}
|
|
768
|
+
`
|
|
769
|
+
}),
|
|
770
|
+
isClickableType && /* @__PURE__ */ jsx("input", {
|
|
771
|
+
type: "hidden",
|
|
772
|
+
name,
|
|
773
|
+
value
|
|
774
|
+
}),
|
|
775
|
+
isOpen && isDateType && !inputProps.disabled && /* @__PURE__ */ jsx(DateTimePickerPopup, {
|
|
776
|
+
value: getDateValue(),
|
|
777
|
+
onChange: handleDateChange,
|
|
778
|
+
type,
|
|
779
|
+
onClose: () => setIsOpen(false),
|
|
780
|
+
anchorName
|
|
781
|
+
}),
|
|
782
|
+
isOpen && isColorType && !inputProps.disabled && /* @__PURE__ */ jsx(ColorPickerPopup, {
|
|
783
|
+
value: value || "",
|
|
784
|
+
onChange: handleColorChange,
|
|
785
|
+
onClose: () => setIsOpen(false),
|
|
786
|
+
anchorName
|
|
787
|
+
})
|
|
788
|
+
]
|
|
789
|
+
})
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
//#endregion
|
|
793
|
+
//#region src/components/inputs/searchInput.tsx
|
|
794
|
+
function SearchInput({ placeholder = "Search...", variant = "default" }) {
|
|
795
|
+
const router = useRouter();
|
|
796
|
+
const pathname = usePathname();
|
|
797
|
+
const searchParams = useSearchParams();
|
|
798
|
+
const [searchValue, setSearchValue] = useState(searchParams.get("q") || "");
|
|
799
|
+
useEffect(() => {
|
|
800
|
+
setSearchValue(searchParams.get("q") || "");
|
|
801
|
+
}, [searchParams]);
|
|
802
|
+
function handleSearch(value) {
|
|
803
|
+
setSearchValue(value);
|
|
804
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
805
|
+
if (value.trim()) params.set("q", value.trim());
|
|
806
|
+
else params.delete("q");
|
|
807
|
+
params.delete("page");
|
|
808
|
+
router.push(`${pathname}?${params.toString()}`);
|
|
809
|
+
}
|
|
810
|
+
function handleKeyDown(e) {
|
|
811
|
+
if (e.key === "Enter") handleSearch(searchValue);
|
|
812
|
+
}
|
|
813
|
+
function handleChange(e) {
|
|
814
|
+
setSearchValue(e.target.value);
|
|
815
|
+
}
|
|
816
|
+
if (variant === "minimal") return /* @__PURE__ */ jsxs("div", {
|
|
817
|
+
className: "relative",
|
|
818
|
+
children: [/* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5" }), /* @__PURE__ */ jsx("input", {
|
|
819
|
+
type: "text",
|
|
820
|
+
value: searchValue,
|
|
821
|
+
onChange: (e) => setSearchValue(e.target.value),
|
|
822
|
+
onKeyDown: handleKeyDown,
|
|
823
|
+
onBlur: () => handleSearch(searchValue),
|
|
824
|
+
placeholder,
|
|
825
|
+
className: "pl-10 pr-4 py-2 border-b outline-none w-64"
|
|
826
|
+
})]
|
|
827
|
+
});
|
|
828
|
+
else return /* @__PURE__ */ jsx(Input, {
|
|
829
|
+
name: "search",
|
|
830
|
+
icon: /* @__PURE__ */ jsx(Search, { className: "w-5 h-5" }),
|
|
831
|
+
value: searchValue,
|
|
832
|
+
onChange: handleChange,
|
|
833
|
+
onKeyDown: handleKeyDown,
|
|
834
|
+
onBlur: () => handleSearch(searchValue),
|
|
835
|
+
placeholder
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
//#endregion
|
|
839
|
+
//#region src/components/inputs/textarea.tsx
|
|
840
|
+
function isValidJson(str) {
|
|
841
|
+
try {
|
|
842
|
+
JSON.parse(str);
|
|
843
|
+
return null;
|
|
844
|
+
} catch (error) {
|
|
845
|
+
return error.message;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
function Textarea(props) {
|
|
849
|
+
const { name, label, error, className, info, description, type = "text", rows = 4, textSize = "sm", ...textareaProps } = props;
|
|
850
|
+
const { value } = textareaProps;
|
|
851
|
+
const [preview, setPreview] = useState(false);
|
|
852
|
+
const displayError = (type === "json" && value ? isValidJson(value) : void 0) || error;
|
|
853
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
854
|
+
label,
|
|
855
|
+
name,
|
|
856
|
+
required: textareaProps.required,
|
|
857
|
+
info,
|
|
858
|
+
description,
|
|
859
|
+
error: displayError,
|
|
860
|
+
textSize,
|
|
861
|
+
className,
|
|
862
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
863
|
+
className: "relative",
|
|
864
|
+
children: [
|
|
865
|
+
type === "markdown" && /* @__PURE__ */ jsx("div", {
|
|
866
|
+
className: "absolute right-2 top-2 z-10 flex gap-2",
|
|
867
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
868
|
+
type: "button",
|
|
869
|
+
onClick: () => setPreview(!preview),
|
|
870
|
+
className: "p-1 rounded hover:bg-login-500/50 text-login-text transition-colors",
|
|
871
|
+
title: preview ? "Edit" : "Preview",
|
|
872
|
+
children: preview ? /* @__PURE__ */ jsx(Pencil, { size: 16 }) : /* @__PURE__ */ jsx(Eye, { size: 16 })
|
|
873
|
+
})
|
|
874
|
+
}),
|
|
875
|
+
type === "markdown" && preview && /* @__PURE__ */ jsx("div", {
|
|
876
|
+
className: `
|
|
877
|
+
w-full rounded-md bg-login-500/50 border border-login-500
|
|
878
|
+
p-3 overflow-y-auto ${error ? "border-red-500/70" : ""}
|
|
879
|
+
`,
|
|
880
|
+
children: /* @__PURE__ */ jsx(MarkdownRender, { MDstr: String(value || "") })
|
|
881
|
+
}),
|
|
882
|
+
/* @__PURE__ */ jsx("textarea", {
|
|
883
|
+
...textareaProps,
|
|
884
|
+
id: name,
|
|
885
|
+
name,
|
|
886
|
+
rows,
|
|
887
|
+
title: label,
|
|
888
|
+
"aria-invalid": !!error,
|
|
889
|
+
"aria-describedby": error ? `${name}-error` : void 0,
|
|
890
|
+
className: `
|
|
891
|
+
${type === "markdown" && preview ? "hidden" : ""}
|
|
892
|
+
w-full rounded-md bg-login-500/50 border border-login-500
|
|
893
|
+
text-login-text placeholder-login-200 text-sm
|
|
894
|
+
focus:outline-none focus:border-login/60 focus:ring-1 focus:ring-login/30
|
|
895
|
+
disabled:opacity-40 disabled:cursor-not-allowed
|
|
896
|
+
p-3 pr-10
|
|
897
|
+
transition-all duration-150
|
|
898
|
+
resize-y
|
|
899
|
+
${error ? "border-red-500/70 focus:border-red-500/70 focus:ring-red-500/30" : ""}
|
|
900
|
+
`
|
|
901
|
+
})
|
|
902
|
+
]
|
|
903
|
+
})
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
//#endregion
|
|
907
|
+
//#region src/components/inputs/checkbox.tsx
|
|
908
|
+
function Checkbox(props) {
|
|
909
|
+
const { options, onChange, value, label, description, error, info, name, className, textSize = "sm", ...rest } = props;
|
|
910
|
+
const selectedValues = Array.isArray(value) ? value : [];
|
|
911
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
912
|
+
label,
|
|
913
|
+
name,
|
|
914
|
+
required: rest.required,
|
|
915
|
+
info,
|
|
916
|
+
description,
|
|
917
|
+
error,
|
|
918
|
+
textSize,
|
|
919
|
+
className,
|
|
920
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
921
|
+
className: "flex flex-col gap-2",
|
|
922
|
+
children: options.map((option) => /* @__PURE__ */ jsx(CheckboxItem, {
|
|
923
|
+
name,
|
|
924
|
+
value: option.value,
|
|
925
|
+
label: option.label,
|
|
926
|
+
checked: selectedValues.includes(option.value),
|
|
927
|
+
disabled: rest.disabled,
|
|
928
|
+
onChange: (e) => {
|
|
929
|
+
if (!onChange) return;
|
|
930
|
+
const isChecked = e.target.checked;
|
|
931
|
+
let newValues = [...selectedValues];
|
|
932
|
+
if (isChecked) newValues.push(option.value);
|
|
933
|
+
else newValues = newValues.filter((v) => v !== option.value);
|
|
934
|
+
onChange(newValues);
|
|
935
|
+
},
|
|
936
|
+
className: "mb-0"
|
|
937
|
+
}, option.value))
|
|
938
|
+
})
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
function CheckboxItem(props) {
|
|
942
|
+
const { name, label, error, ...inputProps } = props;
|
|
943
|
+
const id = inputProps.value ? `${name}-${inputProps.value}` : name;
|
|
944
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
945
|
+
className: "flex items-center gap-2",
|
|
946
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
947
|
+
className: "relative w-5 h-5 shrink-0",
|
|
948
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
949
|
+
...inputProps,
|
|
950
|
+
id,
|
|
951
|
+
name,
|
|
952
|
+
type: "checkbox",
|
|
953
|
+
className: `
|
|
954
|
+
peer appearance-none rounded border border-login-500 bg-login-500/50
|
|
955
|
+
checked:bg-login checked:border-login
|
|
956
|
+
focus:outline-none focus:ring-1 focus:ring-login/30
|
|
957
|
+
disabled:opacity-40 disabled:cursor-not-allowed
|
|
958
|
+
cursor-pointer transition-all duration-150
|
|
959
|
+
w-5 h-5 absolute inset-0
|
|
960
|
+
${error ? "border-red-500/70" : ""}
|
|
961
|
+
`
|
|
962
|
+
}), /* @__PURE__ */ jsx(Check, { className: `
|
|
963
|
+
absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2
|
|
964
|
+
w-3.5 h-3.5 pointer-events-none text-white opacity-0
|
|
965
|
+
peer-checked:opacity-100 transition-opacity duration-200
|
|
966
|
+
` })]
|
|
967
|
+
}), label && /* @__PURE__ */ jsx(InputLabel, {
|
|
968
|
+
label,
|
|
969
|
+
name,
|
|
970
|
+
disabled: inputProps.disabled,
|
|
971
|
+
className: "select-none cursor-pointer"
|
|
972
|
+
})]
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
//#endregion
|
|
976
|
+
//#region src/components/inputs/select.tsx
|
|
977
|
+
function Select({ label, name, value, onChange, options, error, className, disabled, required, placeholder = "Select an option", info, description, clearable = true, searchable = true, textSize = "sm" }) {
|
|
978
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
979
|
+
const [searchTerm, setSearchTerm] = useState("");
|
|
980
|
+
const [selectedOption, setSelectedOption] = useState(options.find((opt) => opt.value === value));
|
|
981
|
+
useEffect(() => {
|
|
982
|
+
if (!isOpen) setSearchTerm("");
|
|
983
|
+
}, [isOpen]);
|
|
984
|
+
useEffect(() => {
|
|
985
|
+
setSelectedOption(options.find((opt) => opt.value === value));
|
|
986
|
+
}, [value, options]);
|
|
987
|
+
const containerRef = useRef(null);
|
|
988
|
+
useClickOutside(containerRef, () => setIsOpen(false));
|
|
989
|
+
function handleSelect(option) {
|
|
990
|
+
if (disabled) return;
|
|
991
|
+
setSelectedOption(option);
|
|
992
|
+
setIsOpen(false);
|
|
993
|
+
if (onChange) onChange(option.value);
|
|
994
|
+
}
|
|
995
|
+
function handleClear(e) {
|
|
996
|
+
e.stopPropagation();
|
|
997
|
+
if (disabled) return;
|
|
998
|
+
setSelectedOption(void 0);
|
|
999
|
+
if (onChange) onChange(null);
|
|
1000
|
+
}
|
|
1001
|
+
const filteredOptions = options.filter((option) => option.label.toLowerCase().includes(searchTerm.toLowerCase()));
|
|
1002
|
+
return /* @__PURE__ */ jsxs(FieldWrapper, {
|
|
1003
|
+
label,
|
|
1004
|
+
name,
|
|
1005
|
+
required,
|
|
1006
|
+
info,
|
|
1007
|
+
description,
|
|
1008
|
+
error,
|
|
1009
|
+
textSize,
|
|
1010
|
+
className,
|
|
1011
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1012
|
+
className: "relative",
|
|
1013
|
+
ref: containerRef,
|
|
1014
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
1015
|
+
type: "button",
|
|
1016
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1017
|
+
disabled,
|
|
1018
|
+
"aria-haspopup": "listbox",
|
|
1019
|
+
"aria-expanded": isOpen,
|
|
1020
|
+
"aria-labelledby": label ? void 0 : name,
|
|
1021
|
+
className: `
|
|
1022
|
+
w-full rounded-md bg-login-500/50 border border-login-500
|
|
1023
|
+
text-login-text text-left text-sm
|
|
1024
|
+
focus:outline-none focus:border-login/60 focus:ring-1 focus:ring-login/30
|
|
1025
|
+
disabled:opacity-40 disabled:cursor-not-allowed
|
|
1026
|
+
h-10 py-2 pl-3 pr-10
|
|
1027
|
+
transition-all duration-150
|
|
1028
|
+
flex items-center justify-between
|
|
1029
|
+
${error ? "border-red-500/70 focus:border-red-500/70 focus:ring-red-500/30" : ""}
|
|
1030
|
+
${!selectedOption ? "text-login-200" : ""}
|
|
1031
|
+
`,
|
|
1032
|
+
title: label,
|
|
1033
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1034
|
+
className: "flex items-center gap-2 truncate",
|
|
1035
|
+
children: [selectedOption?.image && /* @__PURE__ */ jsx(Image, {
|
|
1036
|
+
src: selectedOption.image,
|
|
1037
|
+
alt: "",
|
|
1038
|
+
width: 30,
|
|
1039
|
+
height: 20,
|
|
1040
|
+
className: "rounded-xs object-cover shrink-0"
|
|
1041
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1042
|
+
className: "truncate",
|
|
1043
|
+
children: selectedOption ? selectedOption.label : placeholder
|
|
1044
|
+
})]
|
|
1045
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1046
|
+
className: "absolute inset-y-0 right-0 flex items-center px-2 gap-1",
|
|
1047
|
+
children: [clearable && selectedOption && !disabled && /* @__PURE__ */ jsx("div", {
|
|
1048
|
+
role: "button",
|
|
1049
|
+
onClick: handleClear,
|
|
1050
|
+
className: `
|
|
1051
|
+
p-1 hover:bg-login-500 rounded-full text-login-200
|
|
1052
|
+
hover:text-red-400 transition-colors cursor-pointer
|
|
1053
|
+
`,
|
|
1054
|
+
title: "Clear selection",
|
|
1055
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-3 h-3" })
|
|
1056
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1057
|
+
className: `
|
|
1058
|
+
text-login-200 pointer-events-none
|
|
1059
|
+
transition-transform duration-200
|
|
1060
|
+
${isOpen ? "rotate-180" : ""}
|
|
1061
|
+
`,
|
|
1062
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "w-4 h-4" })
|
|
1063
|
+
})]
|
|
1064
|
+
})]
|
|
1065
|
+
}), isOpen && /* @__PURE__ */ jsxs("div", {
|
|
1066
|
+
className: `
|
|
1067
|
+
absolute z-50 w-full mt-1 bg-login-700 border border-login-500/50
|
|
1068
|
+
rounded-md shadow-xl max-h-60 overflow-hidden flex flex-col
|
|
1069
|
+
`,
|
|
1070
|
+
children: [searchable && /* @__PURE__ */ jsx("div", {
|
|
1071
|
+
className: "p-2 sticky top-0 bg-login-700 border-b border-login-500/20 z-10",
|
|
1072
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1073
|
+
className: "relative",
|
|
1074
|
+
children: [/* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-login-200" }), /* @__PURE__ */ jsx("input", {
|
|
1075
|
+
type: "text",
|
|
1076
|
+
value: searchTerm,
|
|
1077
|
+
onChange: (e) => setSearchTerm(e.target.value),
|
|
1078
|
+
placeholder: "Search...",
|
|
1079
|
+
autoFocus: true,
|
|
1080
|
+
className: `
|
|
1081
|
+
w-full bg-login-600 border border-login-500/50 rounded-md
|
|
1082
|
+
py-1.5 pl-9 pr-3 text-sm text-login-text
|
|
1083
|
+
focus:outline-none focus:border-login/60 focus:ring-1 focus:ring-login/30
|
|
1084
|
+
`
|
|
1085
|
+
})]
|
|
1086
|
+
})
|
|
1087
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1088
|
+
className: "overflow-auto noscroll",
|
|
1089
|
+
children: filteredOptions.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
1090
|
+
className: "py-1",
|
|
1091
|
+
role: "listbox",
|
|
1092
|
+
children: filteredOptions.map((option) => /* @__PURE__ */ jsx("li", {
|
|
1093
|
+
role: "option",
|
|
1094
|
+
"aria-selected": selectedOption?.value === option.value,
|
|
1095
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
1096
|
+
type: "button",
|
|
1097
|
+
onClick: () => handleSelect(option),
|
|
1098
|
+
className: `
|
|
1099
|
+
w-full text-left px-3 py-2 text-sm
|
|
1100
|
+
hover:bg-login-600 transition-colors duration-150
|
|
1101
|
+
flex items-center gap-2
|
|
1102
|
+
${selectedOption?.value === option.value ? "bg-login/15 text-login" : "text-login-text"}
|
|
1103
|
+
`,
|
|
1104
|
+
children: [option.image && /* @__PURE__ */ jsx(Image, {
|
|
1105
|
+
src: option.image,
|
|
1106
|
+
alt: "",
|
|
1107
|
+
width: 75,
|
|
1108
|
+
height: 25,
|
|
1109
|
+
className: "rounded-md object-cover shrink-0"
|
|
1110
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1111
|
+
className: "truncate",
|
|
1112
|
+
children: option.label
|
|
1113
|
+
})]
|
|
1114
|
+
})
|
|
1115
|
+
}, option.value))
|
|
1116
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
1117
|
+
className: "px-3 py-2 text-sm text-login-200",
|
|
1118
|
+
children: searchTerm ? "No results found" : "No options available"
|
|
1119
|
+
})
|
|
1120
|
+
})]
|
|
1121
|
+
})]
|
|
1122
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
1123
|
+
type: "hidden",
|
|
1124
|
+
name,
|
|
1125
|
+
value: selectedOption?.value || "",
|
|
1126
|
+
required
|
|
1127
|
+
})]
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
//#endregion
|
|
1131
|
+
//#region src/components/inputs/tagInput.tsx
|
|
1132
|
+
function TagInput({ label, name, value = [], onChange, placeholder = "Add...", error, className, disabled, required, info, description, textSize = "sm" }) {
|
|
1133
|
+
const [inputValue, setInputValue] = useState("");
|
|
1134
|
+
function handleKeyDown(e) {
|
|
1135
|
+
if ((e.key === "Enter" || e.key === ",") && inputValue.trim()) {
|
|
1136
|
+
e.preventDefault();
|
|
1137
|
+
const val = inputValue.trim().replace(/,$/, "");
|
|
1138
|
+
if (val && !value.includes(val)) {
|
|
1139
|
+
const newValue = [...value, val];
|
|
1140
|
+
if (onChange) onChange(newValue);
|
|
1141
|
+
}
|
|
1142
|
+
setInputValue("");
|
|
1143
|
+
} else if (e.key === "Backspace" && !inputValue && value.length > 0) {
|
|
1144
|
+
const newValue = value.slice(0, -1);
|
|
1145
|
+
if (onChange) onChange(newValue);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
function removeTag(index) {
|
|
1149
|
+
if (disabled) return;
|
|
1150
|
+
const newValue = value.filter((_, i) => i !== index);
|
|
1151
|
+
if (onChange) onChange(newValue);
|
|
1152
|
+
}
|
|
1153
|
+
return /* @__PURE__ */ jsxs(FieldWrapper, {
|
|
1154
|
+
label,
|
|
1155
|
+
name,
|
|
1156
|
+
required,
|
|
1157
|
+
info,
|
|
1158
|
+
description,
|
|
1159
|
+
error,
|
|
1160
|
+
className,
|
|
1161
|
+
textSize,
|
|
1162
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1163
|
+
className: `
|
|
1164
|
+
flex flex-wrap gap-2 p-2 rounded-md bg-login-500/50 border border-login-500
|
|
1165
|
+
text-login-text min-h-10
|
|
1166
|
+
focus-within:border-login/60 focus-within:ring-1 focus-within:ring-login/30
|
|
1167
|
+
transition-all duration-150
|
|
1168
|
+
${error ? "border-red-500/70 focus-within:border-red-500/70 focus-within:ring-red-500/30" : ""}
|
|
1169
|
+
`,
|
|
1170
|
+
children: [value.map((tag, index) => /* @__PURE__ */ jsxs("span", {
|
|
1171
|
+
className: "flex items-center gap-1 px-2 py-0.5 bg-login-600 text-login-100 border border-login-500 rounded text-sm",
|
|
1172
|
+
children: [tag, !disabled && /* @__PURE__ */ jsx("button", {
|
|
1173
|
+
type: "button",
|
|
1174
|
+
onClick: () => removeTag(index),
|
|
1175
|
+
className: "hover:text-red-200 transition-colors",
|
|
1176
|
+
children: /* @__PURE__ */ jsx(X, { size: 14 })
|
|
1177
|
+
})]
|
|
1178
|
+
}, index)), /* @__PURE__ */ jsx("input", {
|
|
1179
|
+
type: "text",
|
|
1180
|
+
value: inputValue,
|
|
1181
|
+
required: required && value.length === 0,
|
|
1182
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
1183
|
+
onKeyDown: handleKeyDown,
|
|
1184
|
+
disabled,
|
|
1185
|
+
placeholder: value.length === 0 ? placeholder : "",
|
|
1186
|
+
className: "flex-1 bg-transparent outline-none min-w-30 text-login-text placeholder:text-login-200"
|
|
1187
|
+
})]
|
|
1188
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
1189
|
+
type: "hidden",
|
|
1190
|
+
name,
|
|
1191
|
+
value: value.join(",")
|
|
1192
|
+
})]
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
//#endregion
|
|
1196
|
+
//#region src/components/inputs/multiSelect.tsx
|
|
1197
|
+
function MultiSelect({ label, name, options, value = [], onChange, placeholder = "Select…", error, className, disabled, required, info, description, textSize = "sm" }) {
|
|
1198
|
+
const [open, setOpen] = useState(false);
|
|
1199
|
+
const containerRef = useRef(null);
|
|
1200
|
+
useClickOutside(containerRef, () => setOpen(false));
|
|
1201
|
+
function toggleOption(optionValue) {
|
|
1202
|
+
if (!onChange) return;
|
|
1203
|
+
if (value.includes(optionValue)) onChange(value.filter((v) => v !== optionValue));
|
|
1204
|
+
else onChange([...value, optionValue]);
|
|
1205
|
+
}
|
|
1206
|
+
function removeOption(optionValue) {
|
|
1207
|
+
if (!onChange) return;
|
|
1208
|
+
onChange(value.filter((v) => v !== optionValue));
|
|
1209
|
+
}
|
|
1210
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
1211
|
+
label,
|
|
1212
|
+
name,
|
|
1213
|
+
required,
|
|
1214
|
+
info,
|
|
1215
|
+
description,
|
|
1216
|
+
error,
|
|
1217
|
+
className,
|
|
1218
|
+
textSize,
|
|
1219
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1220
|
+
ref: containerRef,
|
|
1221
|
+
className: "relative w-full",
|
|
1222
|
+
children: [
|
|
1223
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1224
|
+
onClick: () => !disabled && setOpen((o) => !o),
|
|
1225
|
+
className: `
|
|
1226
|
+
flex min-h-10 cursor-pointer items-center justify-between gap-2
|
|
1227
|
+
rounded-md bg-login-500/50 border border-login-500 px-3 py-1.5
|
|
1228
|
+
transition-all duration-150 select-none
|
|
1229
|
+
${open ? "border-login/60 ring-1 ring-login/30" : ""}
|
|
1230
|
+
${error ? "border-red-500/70" : ""}
|
|
1231
|
+
${disabled ? "opacity-40 cursor-not-allowed" : ""}
|
|
1232
|
+
`,
|
|
1233
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1234
|
+
className: "flex flex-wrap gap-1.5",
|
|
1235
|
+
children: [value.length === 0 && /* @__PURE__ */ jsx("span", {
|
|
1236
|
+
className: "text-sm text-login-200",
|
|
1237
|
+
children: placeholder
|
|
1238
|
+
}), value.map((val) => {
|
|
1239
|
+
const option = options.find((o) => o.value === val);
|
|
1240
|
+
if (!option) return null;
|
|
1241
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
1242
|
+
className: "flex items-center gap-1 px-2 py-0.5 bg-login-600 text-login-100 border border-login-500 rounded text-sm",
|
|
1243
|
+
children: [option.label, !disabled && /* @__PURE__ */ jsx("button", {
|
|
1244
|
+
type: "button",
|
|
1245
|
+
onClick: (e) => {
|
|
1246
|
+
e.stopPropagation();
|
|
1247
|
+
removeOption(val);
|
|
1248
|
+
},
|
|
1249
|
+
className: "hover:text-red-300 transition-colors",
|
|
1250
|
+
children: /* @__PURE__ */ jsx(X, { size: 13 })
|
|
1251
|
+
})]
|
|
1252
|
+
}, val);
|
|
1253
|
+
})]
|
|
1254
|
+
}), /* @__PURE__ */ jsx(ChevronDown, {
|
|
1255
|
+
size: 16,
|
|
1256
|
+
className: `shrink-0 text-login-200 transition-transform duration-150 ${open ? "rotate-180" : ""}`
|
|
1257
|
+
})]
|
|
1258
|
+
}),
|
|
1259
|
+
open && options.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1260
|
+
className: "absolute z-50 mt-1 w-full max-h-60 overflow-auto rounded-md bg-login-800 border border-login-500/50 shadow-lg",
|
|
1261
|
+
children: options.map((option) => {
|
|
1262
|
+
const selected = value.includes(option.value);
|
|
1263
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1264
|
+
onClick: () => toggleOption(option.value),
|
|
1265
|
+
className: `
|
|
1266
|
+
flex cursor-pointer items-center justify-between px-3 py-2 text-sm
|
|
1267
|
+
hover:bg-login-700 transition-colors select-none
|
|
1268
|
+
${selected ? "text-login-50" : "text-login-100"}
|
|
1269
|
+
`,
|
|
1270
|
+
children: [/* @__PURE__ */ jsx("span", { children: option.label }), selected && /* @__PURE__ */ jsx(Check, {
|
|
1271
|
+
size: 14,
|
|
1272
|
+
className: "text-login shrink-0"
|
|
1273
|
+
})]
|
|
1274
|
+
}, option.value);
|
|
1275
|
+
})
|
|
1276
|
+
}),
|
|
1277
|
+
/* @__PURE__ */ jsx("input", {
|
|
1278
|
+
type: "hidden",
|
|
1279
|
+
name,
|
|
1280
|
+
value: value.join(",")
|
|
1281
|
+
})
|
|
1282
|
+
]
|
|
1283
|
+
})
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
//#endregion
|
|
1287
|
+
//#region src/components/inputs/switch.tsx
|
|
1288
|
+
function Switch(props) {
|
|
1289
|
+
const { name, label, error, info, description, className, switchOnly, textSize = "sm", ...inputProps } = props;
|
|
1290
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
1291
|
+
label,
|
|
1292
|
+
name,
|
|
1293
|
+
required: inputProps.required,
|
|
1294
|
+
info,
|
|
1295
|
+
error,
|
|
1296
|
+
description,
|
|
1297
|
+
textSize,
|
|
1298
|
+
className,
|
|
1299
|
+
children: /* @__PURE__ */ jsxs("label", {
|
|
1300
|
+
className: `relative inline-flex items-center cursor-pointer ${switchOnly ? "h-fit" : "h-10"}`,
|
|
1301
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
1302
|
+
...inputProps,
|
|
1303
|
+
type: "checkbox",
|
|
1304
|
+
id: name,
|
|
1305
|
+
name,
|
|
1306
|
+
className: "sr-only peer"
|
|
1307
|
+
}), /* @__PURE__ */ jsx("div", { className: `
|
|
1308
|
+
w-11 h-6 bg-login-600 rounded-full peer
|
|
1309
|
+
peer-checked:after:translate-x-full peer-checked:after:border-white
|
|
1310
|
+
after:content-[''] after:absolute ${switchOnly ? "after:top-0.5" : "after:top-2.75"} after:left-0.5
|
|
1311
|
+
after:bg-white after:border-gray-300 after:border after:rounded-full
|
|
1312
|
+
after:h-5 after:w-5 after:transition-all peer-checked:bg-login
|
|
1313
|
+
${inputProps.disabled ? "opacity-40 cursor-not-allowed" : ""}
|
|
1314
|
+
${error ? "ring-1 ring-red-500/60" : ""}
|
|
1315
|
+
` })]
|
|
1316
|
+
})
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
//#endregion
|
|
1320
|
+
//#region src/components/inputs/radio.tsx
|
|
1321
|
+
function Radio(props) {
|
|
1322
|
+
const { options, onChange, value, label, description, error, info, name, className, textSize = "sm", ...rest } = props;
|
|
1323
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
1324
|
+
label,
|
|
1325
|
+
name,
|
|
1326
|
+
required: rest.required,
|
|
1327
|
+
info,
|
|
1328
|
+
description,
|
|
1329
|
+
error,
|
|
1330
|
+
textSize,
|
|
1331
|
+
className,
|
|
1332
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1333
|
+
className: "flex flex-col gap-2",
|
|
1334
|
+
children: options.map((option) => /* @__PURE__ */ jsx(RadioItem, {
|
|
1335
|
+
name,
|
|
1336
|
+
value: option.value,
|
|
1337
|
+
label: option.label,
|
|
1338
|
+
checked: value === option.value,
|
|
1339
|
+
disabled: rest.disabled,
|
|
1340
|
+
onChange: () => {
|
|
1341
|
+
if (onChange) onChange(option.value);
|
|
1342
|
+
},
|
|
1343
|
+
className: "mb-0"
|
|
1344
|
+
}, option.value))
|
|
1345
|
+
})
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
function RadioItem(props) {
|
|
1349
|
+
const { name, label, error, ...inputProps } = props;
|
|
1350
|
+
const { value } = inputProps;
|
|
1351
|
+
const id = `${name}-${value}`;
|
|
1352
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1353
|
+
className: "flex items-center gap-2",
|
|
1354
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1355
|
+
className: "relative w-5 h-5 shrink-0",
|
|
1356
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
1357
|
+
...inputProps,
|
|
1358
|
+
id,
|
|
1359
|
+
name,
|
|
1360
|
+
type: "radio",
|
|
1361
|
+
className: `
|
|
1362
|
+
peer appearance-none rounded-full border border-login-500 bg-login-500/50
|
|
1363
|
+
checked:bg-login checked:border-login
|
|
1364
|
+
focus:outline-none focus:ring-1 focus:ring-login/30
|
|
1365
|
+
disabled:opacity-40 disabled:cursor-not-allowed
|
|
1366
|
+
cursor-pointer transition-all duration-150
|
|
1367
|
+
w-5 h-5 absolute inset-0
|
|
1368
|
+
${error ? "border-red-500/70" : ""}
|
|
1369
|
+
`
|
|
1370
|
+
}), /* @__PURE__ */ jsx("div", { className: `
|
|
1371
|
+
absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2
|
|
1372
|
+
w-2 h-2 rounded-full bg-white pointer-events-none opacity-0
|
|
1373
|
+
peer-checked:opacity-100 transition-opacity duration-200
|
|
1374
|
+
` })]
|
|
1375
|
+
}), label && /* @__PURE__ */ jsx(InputLabel, {
|
|
1376
|
+
label,
|
|
1377
|
+
name,
|
|
1378
|
+
disabled: inputProps.disabled,
|
|
1379
|
+
className: "select-none cursor-pointer"
|
|
1380
|
+
})]
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
//#endregion
|
|
1384
|
+
//#region src/components/inputs/range.tsx
|
|
1385
|
+
function Range(props) {
|
|
1386
|
+
const { name, label, error, className, info, description, showValue = true, textSize = "sm", ...inputProps } = props;
|
|
1387
|
+
const { min = 0, max = 100, step = 1, value, defaultValue, onChange, ...restInputProps } = inputProps;
|
|
1388
|
+
const displayValue = value ?? defaultValue ?? 0;
|
|
1389
|
+
return /* @__PURE__ */ jsx(FieldWrapper, {
|
|
1390
|
+
label,
|
|
1391
|
+
name,
|
|
1392
|
+
required: restInputProps.required,
|
|
1393
|
+
info,
|
|
1394
|
+
description,
|
|
1395
|
+
error,
|
|
1396
|
+
textSize,
|
|
1397
|
+
className,
|
|
1398
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1399
|
+
className: "flex items-center gap-4",
|
|
1400
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
1401
|
+
...restInputProps,
|
|
1402
|
+
id: name,
|
|
1403
|
+
name,
|
|
1404
|
+
type: "range",
|
|
1405
|
+
min,
|
|
1406
|
+
max,
|
|
1407
|
+
step,
|
|
1408
|
+
...onChange ? {
|
|
1409
|
+
value,
|
|
1410
|
+
onChange
|
|
1411
|
+
} : { defaultValue: value ?? defaultValue ?? 0 },
|
|
1412
|
+
title: label,
|
|
1413
|
+
"aria-invalid": !!error,
|
|
1414
|
+
"aria-describedby": error ? `${name}-error` : void 0,
|
|
1415
|
+
className: `
|
|
1416
|
+
flex-1 h-2 bg-login-500 rounded-lg appearance-none cursor-pointer
|
|
1417
|
+
accent-login
|
|
1418
|
+
[&::-webkit-slider-thumb]:appearance-none
|
|
1419
|
+
[&::-webkit-slider-thumb]:w-4
|
|
1420
|
+
[&::-webkit-slider-thumb]:h-4
|
|
1421
|
+
[&::-webkit-slider-thumb]:rounded-full
|
|
1422
|
+
[&::-webkit-slider-thumb]:bg-login
|
|
1423
|
+
[&::-moz-range-thumb]:w-4
|
|
1424
|
+
[&::-moz-range-thumb]:h-4
|
|
1425
|
+
[&::-moz-range-thumb]:rounded-full
|
|
1426
|
+
[&::-moz-range-thumb]:bg-login
|
|
1427
|
+
[&::-moz-range-thumb]:border-none
|
|
1428
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
1429
|
+
${error ? "accent-red-500" : ""}
|
|
1430
|
+
`
|
|
1431
|
+
}), showValue && /* @__PURE__ */ jsx("span", {
|
|
1432
|
+
className: "text-login-text text-sm font-medium min-w-10 text-right",
|
|
1433
|
+
children: displayValue
|
|
1434
|
+
})]
|
|
1435
|
+
})
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
//#endregion
|
|
1439
|
+
//#region src/components/logo/logo.tsx
|
|
1440
|
+
function Logo({ className }) {
|
|
1441
|
+
const corner = "fill-[var(--foreground)] transition-all duration-1000";
|
|
1442
|
+
const letter = "fill-none stroke-[var(--color-login)] stroke-[3.5px]";
|
|
1443
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
1444
|
+
className: `block w-full max-w-2xl mx-auto ${className || ""}`,
|
|
1445
|
+
viewBox: "0 0 147.02299 59.20511",
|
|
1446
|
+
children: [
|
|
1447
|
+
/* @__PURE__ */ jsx("path", {
|
|
1448
|
+
className: corner,
|
|
1449
|
+
d: "m 28.77713,58.37738 v 0.76465 H 25.531 v -5.61816 h 0.91309 v 4.85351 z"
|
|
1450
|
+
}),
|
|
1451
|
+
/* @__PURE__ */ jsx("path", {
|
|
1452
|
+
className: corner,
|
|
1453
|
+
d: "m 30.47831,59.142 h -0.917 v -5.61813 h 0.917 z"
|
|
1454
|
+
}),
|
|
1455
|
+
/* @__PURE__ */ jsx("path", {
|
|
1456
|
+
className: corner,
|
|
1457
|
+
d: "M 36.46268,53.52387 V 59.142 H 35.99881 A 0.36347,0.36347 0 0 1 35.6785,58.98185 L 32.59256,55.018 c 0.0078,0.07617 0.01368,0.15039 0.01758,0.22461 0.0039,0.07422 0.0059,0.14258 0.0059,0.20508 V 59.142 h -0.80371 v -5.61813 h 0.47656 a 0.71321,0.71321 0 0 1 0.09864,0.0059 0.3128,0.3128 0 0 1 0.07617,0.02148 0.22919,0.22919 0 0 1 0.0664,0.04688 0.63781,0.63781 0 0 1 0.06641,0.07812 l 3.08984,3.96779 c -0.0078,-0.08105 -0.01367,-0.16015 -0.01757,-0.23828 -0.0039,-0.07813 -0.0059,-0.15039 -0.0059,-0.21875 v -3.6631 z"
|
|
1458
|
+
}),
|
|
1459
|
+
/* @__PURE__ */ jsx("path", {
|
|
1460
|
+
className: corner,
|
|
1461
|
+
d: "m 39.84549,57.1684 a 2.91264,2.91264 0 0 1 -0.11523,0.84765 1.748,1.748 0 0 1 -0.34375,0.64063 1.52483,1.52483 0 0 1 -0.56543,0.40527 2.00691,2.00691 0 0 1 -0.78223,0.14258 3.23707,3.23707 0 0 1 -0.40234,-0.0254 3.44454,3.44454 0 0 1 -0.41309,-0.0801 l 0.04688,-0.5459 a 0.2079,0.2079 0 0 1 0.06055,-0.125 0.19754,0.19754 0 0 1 0.14257,-0.0469 0.74035,0.74035 0 0 1 0.18067,0.0293 1.36468,1.36468 0 0 0 0.71387,-0.041 0.74722,0.74722 0 0 0 0.3125,-0.2207 0.9864,0.9864 0 0 0 0.1914,-0.38574 2.19551,2.19551 0 0 0 0.06445,-0.57227 v -3.667 h 0.90918 z"
|
|
1462
|
+
}),
|
|
1463
|
+
/* @__PURE__ */ jsx("path", {
|
|
1464
|
+
className: corner,
|
|
1465
|
+
d: "m 44.6326,58.40473 -0.0039,0.7373 h -3.50391 v -5.61816 h 3.50391 v 0.7373 h -2.58692 v 1.69336 h 2.06739 v 0.71387 h -2.06739 v 1.73633 z"
|
|
1466
|
+
}),
|
|
1467
|
+
/* @__PURE__ */ jsx("path", {
|
|
1468
|
+
className: corner,
|
|
1469
|
+
d: "M 46.53592,54.26117 V 56.06 h 2.19629 v 0.7373 h -2.19629 v 2.3447 h -0.917 v -5.61813 h 3.50391 v 0.7373 z"
|
|
1470
|
+
}),
|
|
1471
|
+
/* @__PURE__ */ jsx("path", {
|
|
1472
|
+
className: corner,
|
|
1473
|
+
d: "m 55.25956,56.33344 a 3.18179,3.18179 0 0 1 -0.20215,1.15039 2.6634,2.6634 0 0 1 -0.57227,0.90722 2.59685,2.59685 0 0 1 -0.88476,0.59473 3.17156,3.17156 0 0 1 -2.29492,0 2.62415,2.62415 0 0 1 -0.88672,-0.59473 2.65327,2.65327 0 0 1 -0.57422,-0.90722 3.37717,3.37717 0 0 1 0,-2.30176 2.67118,2.67118 0 0 1 0.57422,-0.90918 2.61491,2.61491 0 0 1 0.88672,-0.59668 3.1717,3.1717 0 0 1 2.29492,0 2.58781,2.58781 0 0 1 0.88476,0.59668 2.68144,2.68144 0 0 1 0.57227,0.90918 3.1871,3.1871 0 0 1 0.20215,1.15137 z m -0.93164,0 a 2.706,2.706 0 0 0 -0.13086,-0.87012 1.821,1.821 0 0 0 -0.375,-0.65527 1.63008,1.63008 0 0 0 -0.59082,-0.41407 2.16795,2.16795 0 0 0 -1.55664,0 1.65415,1.65415 0 0 0 -0.59278,0.41407 1.84212,1.84212 0 0 0 -0.3789,0.65527 2.92611,2.92611 0 0 0 0,1.74316 1.83766,1.83766 0 0 0 0.3789,0.6543 1.64222,1.64222 0 0 0 0.59278,0.40918 2.19564,2.19564 0 0 0 1.55664,0 1.61838,1.61838 0 0 0 0.59082,-0.40918 1.81652,1.81652 0 0 0 0.375,-0.6543 2.71589,2.71589 0 0 0 0.13086,-0.87304 z"
|
|
1474
|
+
}),
|
|
1475
|
+
/* @__PURE__ */ jsx("path", {
|
|
1476
|
+
className: corner,
|
|
1477
|
+
d: "m 60.534,59.142 h -0.81543 a 0.377,0.377 0 0 1 -0.35156,-0.1875 l -1.31055,-1.8916 a 0.4267,0.4267 0 0 0 -0.14453,-0.14063 0.50286,0.50286 0 0 0 -0.23437,-0.043 H 57.17072 V 59.142 H 56.2576 v -5.61813 h 1.6543 a 3.54427,3.54427 0 0 1 0.9541,0.11328 1.80649,1.80649 0 0 1 0.65723,0.32226 1.25606,1.25606 0 0 1 0.37988,0.501 1.76427,1.76427 0 0 1 0.03516,1.19727 1.50418,1.50418 0 0 1 -0.25293,0.46093 1.61283,1.61283 0 0 1 -0.40821,0.3584 2.04861,2.04861 0 0 1 -0.5498,0.23828 0.92346,0.92346 0 0 1 0.28906,0.28516 z m -2.64551,-2.92578 a 1.763,1.763 0 0 0 0.5459,-0.07617 1.11007,1.11007 0 0 0 0.39063,-0.21289 0.87892,0.87892 0 0 0 0.23437,-0.3252 1.10093,1.10093 0 0 0 0.07715,-0.41992 0.84276,0.84276 0 0 0 -0.30371,-0.70215 1.46527,1.46527 0 0 0 -0.9209,-0.24219 h -0.74121 v 1.97852 z"
|
|
1478
|
+
}),
|
|
1479
|
+
/* @__PURE__ */ jsx("path", {
|
|
1480
|
+
className: corner,
|
|
1481
|
+
d: "m 64.72049,58.40473 -0.0039,0.7373 h -3.50391 v -5.61816 h 3.50391 v 0.7373 h -2.58692 v 1.69336 h 2.06739 v 0.71387 h -2.06739 v 1.73633 z"
|
|
1482
|
+
}),
|
|
1483
|
+
/* @__PURE__ */ jsx("path", {
|
|
1484
|
+
className: corner,
|
|
1485
|
+
d: "M 70.35721,53.52387 V 59.142 H 69.89335 A 0.36347,0.36347 0 0 1 69.57303,58.98185 L 66.4871,55.018 c 0.0078,0.07617 0.01367,0.15039 0.01757,0.22461 0.0039,0.07422 0.0059,0.14258 0.0059,0.20508 V 59.142 h -0.80371 v -5.61813 h 0.47656 a 0.71321,0.71321 0 0 1 0.09864,0.0059 0.3128,0.3128 0 0 1 0.07617,0.02148 0.22936,0.22936 0 0 1 0.06641,0.04688 0.63869,0.63869 0 0 1 0.0664,0.07812 l 3.08985,3.96777 c -0.008,-0.08105 -0.0137,-0.16015 -0.0176,-0.23828 -0.004,-0.07813 -0.006,-0.15039 -0.006,-0.21875 v -3.66308 z"
|
|
1486
|
+
}),
|
|
1487
|
+
/* @__PURE__ */ jsx("path", {
|
|
1488
|
+
className: corner,
|
|
1489
|
+
d: "m 72.6121,59.142 h -0.917 v -5.61813 h 0.917 z"
|
|
1490
|
+
}),
|
|
1491
|
+
/* @__PURE__ */ jsx("path", {
|
|
1492
|
+
className: corner,
|
|
1493
|
+
d: "M 78.59794,53.52387 V 59.142 H 78.13358 A 0.36344,0.36344 0 0 1 77.81327,58.98185 L 74.72733,55.018 c 0.008,0.07617 0.0137,0.15039 0.0176,0.22461 0.004,0.07422 0.006,0.14258 0.006,0.20508 V 59.142 h -0.80371 v -5.61813 h 0.47656 a 0.713,0.713 0 0 1 0.0986,0.0059 0.31254,0.31254 0 0 1 0.0762,0.02148 0.22936,0.22936 0 0 1 0.0664,0.04688 0.63869,0.63869 0 0 1 0.0664,0.07812 l 3.08984,3.96777 c -0.008,-0.08105 -0.0137,-0.16015 -0.0176,-0.23828 -0.004,-0.07813 -0.006,-0.15039 -0.006,-0.21875 v -3.66308 z"
|
|
1494
|
+
}),
|
|
1495
|
+
/* @__PURE__ */ jsx("path", {
|
|
1496
|
+
className: corner,
|
|
1497
|
+
d: "M 84.53544,56.37641 V 58.6 a 3.24425,3.24425 0 0 1 -1.9502,0.60449 3.419,3.419 0 0 1 -1.23535,-0.21289 2.7275,2.7275 0 0 1 -0.94141,-0.59277 2.59231,2.59231 0 0 1 -0.60156,-0.90723 3.08634,3.08634 0 0 1 -0.21,-1.1582 3.23536,3.23536 0 0 1 0.20215,-1.165 2.5484,2.5484 0 0 1 1.49414,-1.498 3.29189,3.29189 0 0 1 1.20215,-0.209 3.52605,3.52605 0 0 1 0.62988,0.05273 3.11559,3.11559 0 0 1 0.54,0.14649 2.535,2.535 0 0 1 0.84668,0.52246 l -0.26074,0.418 a 0.26545,0.26545 0 0 1 -0.16016,0.12109 0.27377,0.27377 0 0 1 -0.21094,-0.04688 c -0.0752,-0.04492 -0.15527,-0.09082 -0.24023,-0.14062 a 2.01137,2.01137 0 0 0 -0.29,-0.13867 2.127,2.127 0 0 0 -0.37891,-0.10547 2.72656,2.72656 0 0 0 -0.50683,-0.041 2.09434,2.09434 0 0 0 -0.80176,0.14649 1.70173,1.70173 0 0 0 -0.61035,0.418 1.84692,1.84692 0 0 0 -0.39063,0.65722 2.5766,2.5766 0 0 0 -0.13672,0.86231 2.62333,2.62333 0 0 0 0.14453,0.89844 1.88731,1.88731 0 0 0 0.41016,0.67187 1.74772,1.74772 0 0 0 0.6416,0.419 2.55647,2.55647 0 0 0 1.459,0.0703 2.80344,2.80344 0 0 0 0.53222,-0.207 V 57.07074 H 82.928 a 0.19287,0.19287 0 0 1 -0.13964,-0.04883 0.16848,0.16848 0 0 1 -0.0508,-0.12695 v -0.51855 z"
|
|
1498
|
+
}),
|
|
1499
|
+
/* @__PURE__ */ jsx("path", {
|
|
1500
|
+
className: corner,
|
|
1501
|
+
d: "m 89.1243,58.40473 -0.004,0.7373 h -3.50391 v -5.61816 h 3.50391 v 0.7373 h -2.58692 v 1.69336 h 2.06739 v 0.71387 h -2.06739 v 1.73633 z"
|
|
1502
|
+
}),
|
|
1503
|
+
/* @__PURE__ */ jsx("path", {
|
|
1504
|
+
className: corner,
|
|
1505
|
+
d: "M 94.761,53.52387 V 59.142 H 94.29713 A 0.36347,0.36347 0 0 1 93.97682,58.98185 L 90.8909,55.018 c 0.008,0.07617 0.0137,0.15039 0.0176,0.22461 0.004,0.07422 0.006,0.14258 0.006,0.20508 V 59.142 h -0.80371 v -5.61813 h 0.47656 a 0.71321,0.71321 0 0 1 0.0986,0.0059 0.3128,0.3128 0 0 1 0.0762,0.02148 0.22919,0.22919 0 0 1 0.0664,0.04688 0.63781,0.63781 0 0 1 0.0664,0.07812 l 3.08984,3.96777 c -0.008,-0.08105 -0.0137,-0.16015 -0.0176,-0.23828 -0.004,-0.07813 -0.006,-0.15039 -0.006,-0.21875 v -3.66308 z"
|
|
1506
|
+
}),
|
|
1507
|
+
/* @__PURE__ */ jsx("path", {
|
|
1508
|
+
className: corner,
|
|
1509
|
+
d: "M 98.95829,54.26117 V 56.06 h 2.19629 v 0.7373 h -2.19629 v 2.3447 h -0.917 v -5.61813 h 3.5039 v 0.7373 z"
|
|
1510
|
+
}),
|
|
1511
|
+
/* @__PURE__ */ jsx("path", {
|
|
1512
|
+
className: corner,
|
|
1513
|
+
d: "m 107.68192,56.33344 a 3.18158,3.18158 0 0 1 -0.20215,1.15039 2.66353,2.66353 0 0 1 -0.57226,0.90722 2.597,2.597 0 0 1 -0.88477,0.59473 3.17156,3.17156 0 0 1 -2.29492,0 2.62415,2.62415 0 0 1 -0.88672,-0.59473 2.65327,2.65327 0 0 1 -0.57422,-0.90722 3.37717,3.37717 0 0 1 0,-2.30176 2.67118,2.67118 0 0 1 0.57422,-0.90918 2.61491,2.61491 0 0 1 0.88672,-0.59668 3.1717,3.1717 0 0 1 2.29492,0 2.588,2.588 0 0 1 0.88477,0.59668 2.68157,2.68157 0 0 1 0.57226,0.90918 3.18689,3.18689 0 0 1 0.20215,1.15137 z m -0.93164,0 a 2.706,2.706 0 0 0 -0.13086,-0.87012 1.82066,1.82066 0 0 0 -0.375,-0.65527 1.63,1.63 0 0 0 -0.59082,-0.41407 2.16795,2.16795 0 0 0 -1.55664,0 1.65411,1.65411 0 0 0 -0.59277,0.41407 1.84214,1.84214 0 0 0 -0.37891,0.65527 2.92632,2.92632 0 0 0 0,1.74316 1.83768,1.83768 0 0 0 0.37891,0.6543 1.64218,1.64218 0 0 0 0.59277,0.40918 2.19564,2.19564 0 0 0 1.55664,0 1.61829,1.61829 0 0 0 0.59082,-0.40918 1.81623,1.81623 0 0 0 0.375,-0.6543 2.71589,2.71589 0 0 0 0.13086,-0.87304 z"
|
|
1514
|
+
}),
|
|
1515
|
+
/* @__PURE__ */ jsx("path", {
|
|
1516
|
+
className: corner,
|
|
1517
|
+
d: "m 112.95731,59.142 h -0.81543 a 0.377,0.377 0 0 1 -0.35156,-0.1875 l -1.31055,-1.8916 a 0.4267,0.4267 0 0 0 -0.14453,-0.14063 0.50286,0.50286 0 0 0 -0.23437,-0.043 H 109.594 V 59.142 h -0.91309 v -5.61813 h 1.6543 a 3.54427,3.54427 0 0 1 0.9541,0.11328 1.80649,1.80649 0 0 1 0.65723,0.32226 1.25606,1.25606 0 0 1 0.37988,0.501 1.76427,1.76427 0 0 1 0.0352,1.19727 1.50418,1.50418 0 0 1 -0.25293,0.46093 1.61283,1.61283 0 0 1 -0.40821,0.3584 2.04861,2.04861 0 0 1 -0.5498,0.23828 0.92346,0.92346 0 0 1 0.28906,0.28516 z m -2.64551,-2.92578 a 1.763,1.763 0 0 0 0.5459,-0.07617 1.11007,1.11007 0 0 0 0.39063,-0.21289 0.87892,0.87892 0 0 0 0.23437,-0.3252 1.10093,1.10093 0 0 0 0.0772,-0.41992 0.84276,0.84276 0 0 0 -0.30371,-0.70215 1.46527,1.46527 0 0 0 -0.9209,-0.24219 H 109.594 v 1.97852 z"
|
|
1518
|
+
}),
|
|
1519
|
+
/* @__PURE__ */ jsx("path", {
|
|
1520
|
+
className: corner,
|
|
1521
|
+
d: "m 116.4954,59.142 h -0.917 v -5.61813 h 0.917 z"
|
|
1522
|
+
}),
|
|
1523
|
+
/* @__PURE__ */ jsx("path", {
|
|
1524
|
+
className: corner,
|
|
1525
|
+
d: "m 121.69559,54.28461 h -1.75195 V 59.142 h -0.9082 v -4.85739 h -1.75586 v -0.76074 h 4.416 z"
|
|
1526
|
+
}),
|
|
1527
|
+
/* @__PURE__ */ jsx("polyline", {
|
|
1528
|
+
className: letter,
|
|
1529
|
+
style: { strokeMiterlimit: 10 },
|
|
1530
|
+
points: "47.871 98.1 33.189 98.1 33.189 83.418",
|
|
1531
|
+
transform: "translate(-31.392,-41.894)"
|
|
1532
|
+
}),
|
|
1533
|
+
/* @__PURE__ */ jsx("polyline", {
|
|
1534
|
+
className: letter,
|
|
1535
|
+
style: { strokeMiterlimit: 10 },
|
|
1536
|
+
points: "33.142 58.326 33.142 43.644 47.824 43.644",
|
|
1537
|
+
transform: "translate(-31.392,-41.894)"
|
|
1538
|
+
}),
|
|
1539
|
+
/* @__PURE__ */ jsx("polyline", {
|
|
1540
|
+
className: letter,
|
|
1541
|
+
style: { strokeMiterlimit: 10 },
|
|
1542
|
+
points: "161.983 98.122 176.665 98.122 176.665 83.44",
|
|
1543
|
+
transform: "translate(-31.392,-41.894)"
|
|
1544
|
+
}),
|
|
1545
|
+
/* @__PURE__ */ jsx("polyline", {
|
|
1546
|
+
className: letter,
|
|
1547
|
+
style: { strokeMiterlimit: 10 },
|
|
1548
|
+
points: "176.665 58.372 176.665 43.69 161.983 43.69",
|
|
1549
|
+
transform: "translate(-31.392,-41.894)"
|
|
1550
|
+
}),
|
|
1551
|
+
/* @__PURE__ */ jsx("path", {
|
|
1552
|
+
className: corner,
|
|
1553
|
+
d: "m 30.02449,40.19351 v 4.12842 H 12.4991 V 13.99038 h 4.92871 v 26.20313 z"
|
|
1554
|
+
}),
|
|
1555
|
+
/* @__PURE__ */ jsx("path", {
|
|
1556
|
+
className: corner,
|
|
1557
|
+
d: "m 61.53523,29.1564 a 17.15942,17.15942 0 0 1 -1.09473,6.21338 14.35971,14.35971 0 0 1 -3.08593,4.89746 14.091,14.091 0 0 1 -4.78125,3.21191 17.1289,17.1289 0 0 1 -12.38575,0 13.98317,13.98317 0 0 1 -7.88867,-8.10937 18.18161,18.18161 0 0 1 0,-12.42725 14.39119,14.39119 0 0 1 3.09668,-4.90771 14.13157,14.13157 0 0 1 4.792,-3.22315 17.13565,17.13565 0 0 1 12.38575,0 14.02046,14.02046 0 0 1 4.78125,3.22315 14.47032,14.47032 0 0 1 3.08593,4.90771 17.16209,17.16209 0 0 1 1.09472,6.21387 z m -5.03418,0 a 14.62587,14.62587 0 0 0 -0.70508,-4.69727 9.9446,9.9446 0 0 0 -2.02246,-3.53906 8.80545,8.80545 0 0 0 -3.1914,-2.23242 11.719,11.719 0 0 0 -8.4043,0 8.90077,8.90077 0 0 0 -3.20117,2.23242 9.96735,9.96735 0 0 0 -2.043,3.53906 15.81644,15.81644 0 0 0 0,9.415 9.847,9.847 0 0 0 2.043,3.52832 8.85094,8.85094 0 0 0 3.20117,2.21192 11.87213,11.87213 0 0 0 8.4043,0 8.75623,8.75623 0 0 0 3.1914,-2.21192 9.82454,9.82454 0 0 0 2.02249,-3.52828 14.69371,14.69371 0 0 0 0.70505,-4.71777 z"
|
|
1558
|
+
}),
|
|
1559
|
+
/* @__PURE__ */ jsx("path", {
|
|
1560
|
+
className: corner,
|
|
1561
|
+
d: "m 91.76082,29.38784 v 12.00635 a 17.5354,17.5354 0 0 1 -10.53125,3.26465 18.41512,18.41512 0 0 1 -6.667,-1.148 14.80254,14.80254 0 0 1 -5.08691,-3.20166 14.0148,14.0148 0 0 1 -3.24316,-4.897 16.691,16.691 0 0 1 -1.1377,-6.25586 17.42935,17.42935 0 0 1 1.09473,-6.2876 13.74023,13.74023 0 0 1 8.06738,-8.08838 17.7222,17.7222 0 0 1 6.48828,-1.127 19.10354,19.10354 0 0 1 3.40137,0.28418 16.85244,16.85244 0 0 1 2.917,0.79 13.68442,13.68442 0 0 1 2.48633,1.22168 13.95372,13.95372 0 0 1 2.085,1.60058 l -1.41113,2.25391 a 1.40229,1.40229 0 0 1 -0.86426,0.65283 1.47784,1.47784 0 0 1 -1.13672,-0.25244 q -0.6123,-0.35816 -1.2959,-0.7583 a 11.33129,11.33129 0 0 0 -1.56933,-0.748 11.53387,11.53387 0 0 0 -2.043,-0.56836 14.78335,14.78335 0 0 0 -2.73828,-0.22119 11.32128,11.32128 0 0 0 -4.32813,0.78955 9.26752,9.26752 0 0 0 -3.29687,2.25391 9.99164,9.99164 0 0 0 -2.10645,3.54931 13.90267,13.90267 0 0 0 -0.7373,4.65528 14.11731,14.11731 0 0 0 0.77929,4.855 10.1425,10.1425 0 0 0 2.21192,3.62305 9.43419,9.43419 0 0 0 3.46484,2.26416 13.81975,13.81975 0 0 0 7.87793,0.3789 15.14816,15.14816 0 0 0 2.875,-1.11621 v -6.02383 h -4.2334 a 1.04883,1.04883 0 0 1 -0.75879,-0.26367 0.90553,0.90553 0 0 1 -0.27343,-0.68457 v -2.80127 z"
|
|
1562
|
+
}),
|
|
1563
|
+
/* @__PURE__ */ jsx("path", {
|
|
1564
|
+
className: corner,
|
|
1565
|
+
d: "M 102.546,44.32193 H 97.59581 V 13.99038 h 4.95019 z"
|
|
1566
|
+
}),
|
|
1567
|
+
/* @__PURE__ */ jsx("path", {
|
|
1568
|
+
className: corner,
|
|
1569
|
+
d: "m 134.8575,13.99038 v 30.33155 h -2.50684 a 2.14219,2.14219 0 0 1 -0.96875,-0.2002 2.26108,2.26108 0 0 1 -0.75879,-0.66357 L 113.962,22.05777 q 0.063,0.61083 0.0947,1.21093 0.0322,0.60058 0.0322,1.106 v 19.94723 h -4.3398 V 13.99038 h 2.57031 a 3.89092,3.89092 0 0 1 0.53711,0.03174 1.53328,1.53328 0 0 1 0.41016,0.11572 1.18964,1.18964 0 0 1 0.35839,0.25293 4.01792,4.01792 0 0 1 0.3584,0.4209 l 16.68164,21.42188 q -0.063,-0.65259 -0.0947,-1.28467 -0.0308,-0.63208 -0.0312,-1.17969 V 13.99038 Z"
|
|
1570
|
+
})
|
|
1571
|
+
]
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
//#endregion
|
|
1575
|
+
//#region src/components/logo/logoSmall.tsx
|
|
1576
|
+
function LogoSmall() {
|
|
1577
|
+
const corner = "fill-login";
|
|
1578
|
+
const letter = "fill-[var(--foreground)] transition-all duration-1000";
|
|
1579
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
1580
|
+
className: "block h-full",
|
|
1581
|
+
viewBox: "0 0 100 100",
|
|
1582
|
+
fill: "none",
|
|
1583
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1584
|
+
children: [
|
|
1585
|
+
/* @__PURE__ */ jsx("path", {
|
|
1586
|
+
className: corner,
|
|
1587
|
+
d: "M0 0H6.6667V28.3333H0V0Z"
|
|
1588
|
+
}),
|
|
1589
|
+
/* @__PURE__ */ jsx("path", {
|
|
1590
|
+
className: corner,
|
|
1591
|
+
d: "M28.3333 0V6.6667H0V0H28.3333Z"
|
|
1592
|
+
}),
|
|
1593
|
+
/* @__PURE__ */ jsx("path", {
|
|
1594
|
+
className: corner,
|
|
1595
|
+
d: "M100 0V6.6667H71.6667V0H100Z"
|
|
1596
|
+
}),
|
|
1597
|
+
/* @__PURE__ */ jsx("path", {
|
|
1598
|
+
className: corner,
|
|
1599
|
+
d: "M100 28.3333H93.3333V0H100V28.3333Z"
|
|
1600
|
+
}),
|
|
1601
|
+
/* @__PURE__ */ jsx("path", {
|
|
1602
|
+
className: corner,
|
|
1603
|
+
d: "M0 100V93.3333H28.3333V100H0Z"
|
|
1604
|
+
}),
|
|
1605
|
+
/* @__PURE__ */ jsx("path", {
|
|
1606
|
+
className: corner,
|
|
1607
|
+
d: "M0 71.6667H6.6667V100H0V71.6667Z"
|
|
1608
|
+
}),
|
|
1609
|
+
/* @__PURE__ */ jsx("path", {
|
|
1610
|
+
className: corner,
|
|
1611
|
+
d: "M100 100H93.3333V71.6667H100V100Z"
|
|
1612
|
+
}),
|
|
1613
|
+
/* @__PURE__ */ jsx("path", {
|
|
1614
|
+
className: corner,
|
|
1615
|
+
d: "M71.6667 100V93.3333H100V100H71.6667Z"
|
|
1616
|
+
}),
|
|
1617
|
+
/* @__PURE__ */ jsx("path", {
|
|
1618
|
+
className: letter,
|
|
1619
|
+
d: "M31.6667 18.3333H43.3334V81.6666H31.6667V18.3333Z"
|
|
1620
|
+
}),
|
|
1621
|
+
/* @__PURE__ */ jsx("path", {
|
|
1622
|
+
className: letter,
|
|
1623
|
+
d: "M31.6667 70H68.3334V81.6667H31.6667V70Z"
|
|
1624
|
+
})
|
|
1625
|
+
]
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
//#endregion
|
|
1629
|
+
//#region src/components/toggle/theme.tsx
|
|
1630
|
+
function ThemeToggle({ className }) {
|
|
1631
|
+
const router = useRouter();
|
|
1632
|
+
const [theme, setTheme] = useState("dark");
|
|
1633
|
+
useEffect(() => {
|
|
1634
|
+
const savedTheme = getCookie("theme");
|
|
1635
|
+
if (savedTheme) setTheme(savedTheme);
|
|
1636
|
+
document.documentElement.classList.remove("dark", "light");
|
|
1637
|
+
document.documentElement.classList.add(theme);
|
|
1638
|
+
}, [theme]);
|
|
1639
|
+
function toggleTheme() {
|
|
1640
|
+
const newTheme = theme === "dark" ? "light" : "dark";
|
|
1641
|
+
setCookie("theme", newTheme);
|
|
1642
|
+
setTheme(newTheme);
|
|
1643
|
+
router.refresh();
|
|
1644
|
+
}
|
|
1645
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1646
|
+
className: `grid place-items-center justify-end rounded-md hover:bg-login-300/20 w-fit ${className}`,
|
|
1647
|
+
children: /* @__PURE__ */ jsxs("label", {
|
|
1648
|
+
className: "cursor-pointer",
|
|
1649
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
1650
|
+
type: "checkbox",
|
|
1651
|
+
checked: theme === "light",
|
|
1652
|
+
onChange: toggleTheme,
|
|
1653
|
+
className: "sr-only"
|
|
1654
|
+
}), /* @__PURE__ */ jsx(ThemeIcon, { theme })]
|
|
1655
|
+
})
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
function ThemeIcon({ theme }) {
|
|
1659
|
+
const sunrayClass = `fill-white transition-opacity duration-400 ${theme === "light" ? "opacity-0" : "opacity-100"}`;
|
|
1660
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
1661
|
+
className: "h-12 p-3",
|
|
1662
|
+
viewBox: "0 0 100 100",
|
|
1663
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1664
|
+
children: [
|
|
1665
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("mask", {
|
|
1666
|
+
id: "theme-toggle_clip-path",
|
|
1667
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
1668
|
+
x: "0",
|
|
1669
|
+
y: "0",
|
|
1670
|
+
width: "100",
|
|
1671
|
+
height: "100",
|
|
1672
|
+
fill: "white"
|
|
1673
|
+
}), /* @__PURE__ */ jsx("circle", {
|
|
1674
|
+
className: `transition-transform duration-400 ${theme === "dark" ? "translate-x-8 -translate-y-4" : ""}`,
|
|
1675
|
+
cx: "68",
|
|
1676
|
+
cy: "40",
|
|
1677
|
+
r: "18"
|
|
1678
|
+
})]
|
|
1679
|
+
}) }),
|
|
1680
|
+
/* @__PURE__ */ jsx("circle", {
|
|
1681
|
+
className: `origin-center transition-all duration-400 ${theme === "light" ? "scale-[1.9] fill-black" : "scale-100 fill-white"}`,
|
|
1682
|
+
mask: "url(#theme-toggle_clip-path)",
|
|
1683
|
+
cx: "50",
|
|
1684
|
+
cy: "50",
|
|
1685
|
+
r: "23"
|
|
1686
|
+
}),
|
|
1687
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1688
|
+
className: sunrayClass,
|
|
1689
|
+
x: "86",
|
|
1690
|
+
y: "47",
|
|
1691
|
+
width: "14",
|
|
1692
|
+
height: "6",
|
|
1693
|
+
rx: "3"
|
|
1694
|
+
}),
|
|
1695
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1696
|
+
className: sunrayClass,
|
|
1697
|
+
y: "47",
|
|
1698
|
+
width: "14",
|
|
1699
|
+
height: "6",
|
|
1700
|
+
rx: "3"
|
|
1701
|
+
}),
|
|
1702
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1703
|
+
className: sunrayClass,
|
|
1704
|
+
x: "47",
|
|
1705
|
+
y: "86",
|
|
1706
|
+
width: "6",
|
|
1707
|
+
height: "14",
|
|
1708
|
+
rx: "3"
|
|
1709
|
+
}),
|
|
1710
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1711
|
+
className: sunrayClass,
|
|
1712
|
+
x: "75",
|
|
1713
|
+
y: "75",
|
|
1714
|
+
width: "6",
|
|
1715
|
+
height: "14",
|
|
1716
|
+
rx: "3",
|
|
1717
|
+
transform: "rotate(-45 78 78)"
|
|
1718
|
+
}),
|
|
1719
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1720
|
+
className: sunrayClass,
|
|
1721
|
+
x: "84.8995",
|
|
1722
|
+
y: "12",
|
|
1723
|
+
width: "6",
|
|
1724
|
+
height: "14",
|
|
1725
|
+
rx: "3",
|
|
1726
|
+
transform: "rotate(45 84.8995 12)"
|
|
1727
|
+
}),
|
|
1728
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1729
|
+
className: sunrayClass,
|
|
1730
|
+
x: "22.8995",
|
|
1731
|
+
y: "74",
|
|
1732
|
+
width: "6",
|
|
1733
|
+
height: "14",
|
|
1734
|
+
rx: "3",
|
|
1735
|
+
transform: "rotate(45 22.8995 74)"
|
|
1736
|
+
}),
|
|
1737
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1738
|
+
className: sunrayClass,
|
|
1739
|
+
x: "13",
|
|
1740
|
+
y: "16.2426",
|
|
1741
|
+
width: "6",
|
|
1742
|
+
height: "14",
|
|
1743
|
+
rx: "3",
|
|
1744
|
+
transform: "rotate(-45 13 16.2426)"
|
|
1745
|
+
}),
|
|
1746
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1747
|
+
className: sunrayClass,
|
|
1748
|
+
x: "47",
|
|
1749
|
+
y: "0",
|
|
1750
|
+
width: "6",
|
|
1751
|
+
height: "14",
|
|
1752
|
+
rx: "3"
|
|
1753
|
+
})
|
|
1754
|
+
]
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
//#endregion
|
|
1758
|
+
//#region src/components/toggle/language.tsx
|
|
1759
|
+
function LanguageToggle({ language }) {
|
|
1760
|
+
const [lang, setLang] = useState(language || "en");
|
|
1761
|
+
const [jump, setJump] = useState(false);
|
|
1762
|
+
const router = useRouter();
|
|
1763
|
+
useEffect(() => {
|
|
1764
|
+
const savedLang = getCookie("lang");
|
|
1765
|
+
if (savedLang) setLang(savedLang);
|
|
1766
|
+
}, []);
|
|
1767
|
+
function handleClick() {
|
|
1768
|
+
const newLang = lang === "no" ? "en" : "no";
|
|
1769
|
+
setCookie("lang", newLang);
|
|
1770
|
+
setLang(newLang);
|
|
1771
|
+
language = newLang;
|
|
1772
|
+
setJump(true);
|
|
1773
|
+
setTimeout(() => setJump(false), 400);
|
|
1774
|
+
router.refresh();
|
|
1775
|
+
}
|
|
1776
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
1777
|
+
value: lang,
|
|
1778
|
+
onClick: handleClick,
|
|
1779
|
+
className: `cursor-pointer p-2 leading-8 text-base w-[4.3rem] text-center rounded
|
|
1780
|
+
bg-transparent border-none hover:bg-gray-400/10 flex flex-row items-center justify-center gap-1`,
|
|
1781
|
+
children: [/* @__PURE__ */ jsx(Globe, { className: `text-xl leading-8 -mt-0.5 ${jump ? "animate-jump" : ""}` }), " " + lang]
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
//#endregion
|
|
1785
|
+
//#region src/components/navbar/bubble.tsx
|
|
1786
|
+
function Bubble({ bubble }) {
|
|
1787
|
+
if (bubble.hide) return null;
|
|
1788
|
+
return /* @__PURE__ */ jsxs("a", {
|
|
1789
|
+
href: bubble.href,
|
|
1790
|
+
className: `absolute top-13 min-w-40 ${bubble.className}`,
|
|
1791
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
1792
|
+
viewBox: "0 0 24 12",
|
|
1793
|
+
className: "absolute -top-3 h-3 w-6",
|
|
1794
|
+
"aria-hidden": "true",
|
|
1795
|
+
children: [/* @__PURE__ */ jsx("path", {
|
|
1796
|
+
d: "M12 0 24 12H0Z",
|
|
1797
|
+
fill: bubble.fill,
|
|
1798
|
+
stroke: bubble.stroke,
|
|
1799
|
+
strokeWidth: "1.5",
|
|
1800
|
+
strokeLinejoin: "round"
|
|
1801
|
+
}), /* @__PURE__ */ jsx("path", {
|
|
1802
|
+
d: "M12 0 24 12H0Z",
|
|
1803
|
+
fill: bubble.fill
|
|
1804
|
+
})]
|
|
1805
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1806
|
+
className: "flex justify-between",
|
|
1807
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1808
|
+
className: "min-w-40",
|
|
1809
|
+
children: bubble.text
|
|
1810
|
+
}), /* @__PURE__ */ jsx(X, {
|
|
1811
|
+
onClick: bubble.handleHide,
|
|
1812
|
+
className: bubble.x
|
|
1813
|
+
})]
|
|
1814
|
+
})]
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
//#endregion
|
|
1818
|
+
//#region src/components/navbar/navbar.tsx
|
|
1819
|
+
function Navbar({ children, bubble, className, disableLanguageToggle, disableThemeToggle, innerClassName, lang, loginPath, logoutPath, onlyLogo, profilePath, token }) {
|
|
1820
|
+
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
|
1821
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1822
|
+
className: `${isMobileMenuOpen ? "bg-[#181818f0]" : "bg-[#18181899]"} backdrop-blur-xl fixed top-0 z-900 w-full ${className}`,
|
|
1823
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1824
|
+
className: `flex w-full max-w-6xl m-auto p-2 transition duration-500 800px:justify-between 800px:p-4 ${isMobileMenuOpen ? "h-screen bg-login-900/20 800px:h-20" : ""} ${innerClassName}
|
|
1825
|
+
`,
|
|
1826
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1827
|
+
className: "block h-12 p-1 800px:p-0",
|
|
1828
|
+
children: /* @__PURE__ */ jsx(Link, {
|
|
1829
|
+
href: "/",
|
|
1830
|
+
onClick: () => setIsMobileMenuOpen(false),
|
|
1831
|
+
children: /* @__PURE__ */ jsx(LogoSmall, {})
|
|
1832
|
+
})
|
|
1833
|
+
}), onlyLogo ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1834
|
+
/* @__PURE__ */ jsx("nav", {
|
|
1835
|
+
className: "hidden 800px:flex 800px:justify-between 800px:items-center 800px:w-fill max-w-200",
|
|
1836
|
+
children
|
|
1837
|
+
}),
|
|
1838
|
+
/* @__PURE__ */ jsxs("nav", {
|
|
1839
|
+
className: "flex w-[calc(100vw-8rem)] justify-end h-12 800px:w-fit",
|
|
1840
|
+
children: [
|
|
1841
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1842
|
+
className: "relative grid gap-2",
|
|
1843
|
+
children: [!disableThemeToggle && /* @__PURE__ */ jsx(ThemeToggle, {}), bubble?.theme?.condition && /* @__PURE__ */ jsx(Bubble, { bubble: bubble.theme })]
|
|
1844
|
+
}),
|
|
1845
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1846
|
+
className: "relative grid gap-2",
|
|
1847
|
+
children: [!disableLanguageToggle && /* @__PURE__ */ jsx(LanguageToggle, { language: lang }), bubble?.lang?.condition && /* @__PURE__ */ jsx(Bubble, { bubble: bubble.lang })]
|
|
1848
|
+
}),
|
|
1849
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1850
|
+
className: "relative grid gap-2",
|
|
1851
|
+
children: [loginPath && logoutPath && /* @__PURE__ */ jsx(AuthButton, {
|
|
1852
|
+
profilePath,
|
|
1853
|
+
token,
|
|
1854
|
+
loginPath,
|
|
1855
|
+
logoutPath
|
|
1856
|
+
}), bubble?.login?.condition && /* @__PURE__ */ jsx(Bubble, { bubble: bubble.login })]
|
|
1857
|
+
})
|
|
1858
|
+
]
|
|
1859
|
+
}),
|
|
1860
|
+
/* @__PURE__ */ jsxs("button", {
|
|
1861
|
+
className: "w-12 h-12 relative cursor-pointer bg-none border-none 800px:hidden",
|
|
1862
|
+
onClick: () => setIsMobileMenuOpen(!isMobileMenuOpen),
|
|
1863
|
+
children: [/* @__PURE__ */ jsx("div", { className: hamburgerStyle(isMobileMenuOpen) }), /* @__PURE__ */ jsx("div", { className: hamburgerStyle(isMobileMenuOpen, true) })]
|
|
1864
|
+
}),
|
|
1865
|
+
/* @__PURE__ */ jsx("nav", {
|
|
1866
|
+
className: `fixed top-16 w-[calc(100%-2rem)] max-w-140 mx-auto left-0 right-0 800px:hidden
|
|
1867
|
+
transition-all duration-500 ease-in-out overflow-hidden
|
|
1868
|
+
${isMobileMenuOpen ? "max-h-[calc(100vh-4rem)] opacity-100" : "max-h-0 opacity-0"}`,
|
|
1869
|
+
onClick: () => setIsMobileMenuOpen(false),
|
|
1870
|
+
children: React.Children.map(children, (child, index) => /* @__PURE__ */ jsx("div", {
|
|
1871
|
+
className: `transition-all duration-500 ease-out ${isMobileMenuOpen ? "opacity-100 transform translate-y-0" : "opacity-0 transform -translate-y-4"}`,
|
|
1872
|
+
style: { transitionDelay: isMobileMenuOpen ? `${index * 80}ms` : "0ms" },
|
|
1873
|
+
children: child
|
|
1874
|
+
}, index))
|
|
1875
|
+
})
|
|
1876
|
+
] })]
|
|
1877
|
+
})
|
|
1878
|
+
});
|
|
1879
|
+
}
|
|
1880
|
+
function AuthButton({ profilePath, logoutPath, loginPath, token }) {
|
|
1881
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1882
|
+
className: "rounded-[0.3rem] hover:bg-login-300/20 h-12 w-12",
|
|
1883
|
+
children: token ? /* @__PURE__ */ jsxs(Fragment, { children: [logoutPath && /* @__PURE__ */ jsx(Link, {
|
|
1884
|
+
href: logoutPath,
|
|
1885
|
+
prefetch: false,
|
|
1886
|
+
onClick: (e) => {
|
|
1887
|
+
e.preventDefault();
|
|
1888
|
+
window.location.href = logoutPath;
|
|
1889
|
+
},
|
|
1890
|
+
className: "grid items-center justify-center h-full w-full",
|
|
1891
|
+
children: /* @__PURE__ */ jsx(LogOut, { size: 24 })
|
|
1892
|
+
}), profilePath && /* @__PURE__ */ jsx(Link, {
|
|
1893
|
+
href: profilePath,
|
|
1894
|
+
className: "grid items-center justify-center h-full w-full",
|
|
1895
|
+
children: /* @__PURE__ */ jsx(User, { size: 24 })
|
|
1896
|
+
})] }) : /* @__PURE__ */ jsx(Link, {
|
|
1897
|
+
href: loginPath,
|
|
1898
|
+
className: "grid items-center justify-center h-full w-full",
|
|
1899
|
+
children: /* @__PURE__ */ jsx(User, { size: 24 })
|
|
1900
|
+
})
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1903
|
+
function hamburgerStyle(isOpen, isSecond) {
|
|
1904
|
+
return `bg-login-50 h-0.5 absolute w-8 transition-all duration-[400ms] left-2 ${isOpen ? `top-6 ${isSecond ? "rotate-45" : "-rotate-45"}` : isSecond ? "top-7" : "top-4"}`;
|
|
1905
|
+
}
|
|
1906
|
+
//#endregion
|
|
1907
|
+
//#region src/components/navbar/navbarItem.tsx
|
|
1908
|
+
const commonStyling = "list-none flex no-underline items-center gap-2 whitespace-nowrap cursor-pointer";
|
|
1909
|
+
function NavItem({ href, children, external = false, target, rel, title, icon }) {
|
|
1910
|
+
const linkProps = {
|
|
1911
|
+
href,
|
|
1912
|
+
target,
|
|
1913
|
+
rel,
|
|
1914
|
+
title
|
|
1915
|
+
};
|
|
1916
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Link, {
|
|
1917
|
+
...linkProps,
|
|
1918
|
+
className: "hidden 800px:flex",
|
|
1919
|
+
children: /* @__PURE__ */ jsxs("li", {
|
|
1920
|
+
className: `${commonStyling} text-base leading-4 p-3 font-bold transition-colors link-corner-hover
|
|
1921
|
+
group-[.dropdown]:p-2.5 group-[.dropdown]:pr-3 group-[.dropdown]:pl-1`,
|
|
1922
|
+
children: [
|
|
1923
|
+
icon,
|
|
1924
|
+
children,
|
|
1925
|
+
external && /* @__PURE__ */ jsx(ArrowUpRight, { className: "w-6 h-6 stroke-login" })
|
|
1926
|
+
]
|
|
1927
|
+
})
|
|
1928
|
+
}), /* @__PURE__ */ jsx(Link, {
|
|
1929
|
+
...linkProps,
|
|
1930
|
+
className: "800px:hidden",
|
|
1931
|
+
children: /* @__PURE__ */ jsxs("li", {
|
|
1932
|
+
className: `${commonStyling} text-2xl leading-6 overflow-hidden w-auto pl-4 rounded-[0.3rem] transition-all
|
|
1933
|
+
duration-600 opacity-100 h-16 py-5 group-[.dropdown]:p-0 group-[.dropdown]:text-lg group-[.dropdown]:h-auto
|
|
1934
|
+
group-[.dropdown]:py-2.5 group-[.dropdown]:pl-4`,
|
|
1935
|
+
children: [children, external && /* @__PURE__ */ jsx(ArrowUpRight, { className: "w-6 h-6 stroke-login" })]
|
|
1936
|
+
})
|
|
1937
|
+
})] });
|
|
1938
|
+
}
|
|
1939
|
+
//#endregion
|
|
1940
|
+
//#region src/components/navbar/navbarDropdown.tsx
|
|
1941
|
+
function NavDropdown({ children, title, className }) {
|
|
1942
|
+
const [isMobileDropdownOpen, setIsMobileDropdownOpen] = useState(false);
|
|
1943
|
+
const [isDesktopOpen, setIsDesktopOpen] = useState(false);
|
|
1944
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
1945
|
+
className: "relative hidden 800px:block",
|
|
1946
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1947
|
+
className: "outline-none",
|
|
1948
|
+
tabIndex: 0,
|
|
1949
|
+
ref: useRef(null),
|
|
1950
|
+
onMouseEnter: () => setIsDesktopOpen(true),
|
|
1951
|
+
onMouseLeave: () => setIsDesktopOpen(false),
|
|
1952
|
+
onFocus: () => setIsDesktopOpen(true),
|
|
1953
|
+
onBlur: () => setIsDesktopOpen(false),
|
|
1954
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1955
|
+
className: `list-none no-underline text-base leading-4 p-3 font-bold cursor-pointer flex flex-row items-center
|
|
1956
|
+
transition-colors`,
|
|
1957
|
+
children: [title, /* @__PURE__ */ jsx(ChevronDown, { className: "w-6 h-6 stroke-login ml-1 text-2xl transition-transform duration-300 ease-in-out" })]
|
|
1958
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1959
|
+
className: `absolute pt-2 -ml-4 transition-all duration-200 ease-in-out z-10 ${isDesktopOpen ? "opacity-100 pointer-events-auto translate-y-0" : "opacity-0 pointer-events-none -translate-y-4"}`,
|
|
1960
|
+
children: /* @__PURE__ */ jsx("ul", {
|
|
1961
|
+
className: `p-3 px-6 pb-4 rounded-[0.4rem] shadow-[0_0.1rem_0.5rem_rgba(3,3,3,0.5)] bg-login-700/98 ${className || ""}`,
|
|
1962
|
+
onClick: () => setIsDesktopOpen(false),
|
|
1963
|
+
children: React.Children.map(children, (child, index) => /* @__PURE__ */ jsx("div", {
|
|
1964
|
+
onClick: () => setIsDesktopOpen(false),
|
|
1965
|
+
className: "group dropdown",
|
|
1966
|
+
children: child
|
|
1967
|
+
}, index))
|
|
1968
|
+
})
|
|
1969
|
+
})]
|
|
1970
|
+
})
|
|
1971
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1972
|
+
className: "block 800px:hidden!",
|
|
1973
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
1974
|
+
className: "bg-none border-none cursor-pointer w-full text-left",
|
|
1975
|
+
onClick: (e) => {
|
|
1976
|
+
e.stopPropagation();
|
|
1977
|
+
setIsMobileDropdownOpen(!isMobileDropdownOpen);
|
|
1978
|
+
},
|
|
1979
|
+
children: /* @__PURE__ */ jsxs("li", {
|
|
1980
|
+
className: `list-none no-underline text-2xl leading-6 overflow-hidden
|
|
1981
|
+
w-full pl-4 pr-4 rounded-[0.3rem] transition-all duration-600
|
|
1982
|
+
flex items-center gap-2 opacity-100 min-h-16 py-5 `,
|
|
1983
|
+
children: [/* @__PURE__ */ jsx("span", { children: title }), /* @__PURE__ */ jsx(ChevronDown, { className: `w-6 h-6 transition-transform duration-400 shrink-0
|
|
1984
|
+
${isMobileDropdownOpen ? "rotate-180" : ""}` })]
|
|
1985
|
+
})
|
|
1986
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1987
|
+
className: `list-none no-underline text-xl px-6 ${isMobileDropdownOpen ? "pb-4" : ""}`,
|
|
1988
|
+
children: React.Children.map(children, (child, index) => /* @__PURE__ */ jsx("div", {
|
|
1989
|
+
className: `leading-6 transition-all duration-500 group dropdown
|
|
1990
|
+
${isMobileDropdownOpen ? "h-11 opacity-100" : "h-0 opacity-0"}
|
|
1991
|
+
`,
|
|
1992
|
+
children: child
|
|
1993
|
+
}, index))
|
|
1994
|
+
})]
|
|
1995
|
+
})] });
|
|
1996
|
+
}
|
|
1997
|
+
//#endregion
|
|
1998
|
+
//#region src/components/version/version.tsx
|
|
1999
|
+
function VersionTag({ version, url, className }) {
|
|
2000
|
+
if (!version) return;
|
|
2001
|
+
const style = `w-fit bg-login-700 text-login-100 border border-login-500/40 text-xs font-mono px-2 py-0.5 rounded ${className || ""}`;
|
|
2002
|
+
if (url) return /* @__PURE__ */ jsxs(Link, {
|
|
2003
|
+
className: style,
|
|
2004
|
+
target: "_blank",
|
|
2005
|
+
href: url,
|
|
2006
|
+
children: ["v", version]
|
|
2007
|
+
});
|
|
2008
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2009
|
+
className: style,
|
|
2010
|
+
children: ["v", version]
|
|
2011
|
+
});
|
|
2012
|
+
}
|
|
2013
|
+
//#endregion
|
|
2014
|
+
//#region src/components/footer/footer.tsx
|
|
2015
|
+
function t(s, lang) {
|
|
2016
|
+
return typeof s === "string" ? s : s[lang];
|
|
2017
|
+
}
|
|
2018
|
+
function Footer({ logo, sponsor, columns, socialLinks, copyright, version, lang = "no", className }) {
|
|
2019
|
+
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
2020
|
+
const hasRight = columns && columns.length > 0 || socialLinks && socialLinks.length > 0;
|
|
2021
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2022
|
+
className: `mt-24 bg-login-950 md:mt-40 ${className || ""}`,
|
|
2023
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
2024
|
+
className: `
|
|
2025
|
+
mx-auto w-full px-4 pt-16 pb-24 md:max-w-304 md:px-12 md:pt-20 md:pb-4
|
|
2026
|
+
${hasRight ? "md:grid md:grid-cols-[18rem_1fr] md:gap-x-12" : ""}
|
|
2027
|
+
`,
|
|
2028
|
+
children: [
|
|
2029
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2030
|
+
className: "mx-auto grid w-full max-w-60 gap-16 md:row-span-2 md:max-w-72 md:gap-20",
|
|
2031
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2032
|
+
className: "block w-full",
|
|
2033
|
+
children: logo
|
|
2034
|
+
}), sponsor && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
2035
|
+
className: "block w-full",
|
|
2036
|
+
children: sponsor.node
|
|
2037
|
+
}), sponsor.label && /* @__PURE__ */ jsx("p", {
|
|
2038
|
+
className: "pt-8 text-center text-login-100",
|
|
2039
|
+
children: t(sponsor.label, lang)
|
|
2040
|
+
})] })]
|
|
2041
|
+
}),
|
|
2042
|
+
columns && columns.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
2043
|
+
className: `
|
|
2044
|
+
mt-12 grid w-full max-w-60 gap-8
|
|
2045
|
+
sm:max-w-88 sm:justify-items-end sm:justify-self-end
|
|
2046
|
+
md:col-start-2 md:row-start-1 md:mt-0 md:max-w-136 md:gap-0 md:justify-self-end
|
|
2047
|
+
${columns.length > 1 ? "sm:grid-cols-2" : ""}
|
|
2048
|
+
`,
|
|
2049
|
+
children: columns.map((col, i) => /* @__PURE__ */ jsxs("div", {
|
|
2050
|
+
className: "sm:justify-self-center md:justify-self-end",
|
|
2051
|
+
children: [/* @__PURE__ */ jsx("h4", {
|
|
2052
|
+
className: "pb-2 text-sm font-medium tracking-widest text-login-100",
|
|
2053
|
+
children: t(col.heading, lang)
|
|
2054
|
+
}), col.items.map((item, j) => item.href ? /* @__PURE__ */ jsx("a", {
|
|
2055
|
+
className: "link--underscore-hover block",
|
|
2056
|
+
href: item.href,
|
|
2057
|
+
children: t(item.label, lang)
|
|
2058
|
+
}, j) : /* @__PURE__ */ jsx("p", { children: t(item.label, lang) }, j))]
|
|
2059
|
+
}, i))
|
|
2060
|
+
}),
|
|
2061
|
+
socialLinks && socialLinks.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
2062
|
+
className: "md:col-start-2 md:row-start-2 md:justify-self-end",
|
|
2063
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2064
|
+
className: "mx-auto mt-20 mb-12 flex w-fit flex-wrap justify-center gap-6",
|
|
2065
|
+
children: socialLinks.map((link, i) => /* @__PURE__ */ jsx("a", {
|
|
2066
|
+
className: `block size-8 text-login-100 transition-all duration-200 group ${link.hoverClass ?? "hover:text-login-50"}`,
|
|
2067
|
+
title: link.title,
|
|
2068
|
+
href: link.href,
|
|
2069
|
+
target: "_blank",
|
|
2070
|
+
rel: "noreferrer",
|
|
2071
|
+
children: link.icon
|
|
2072
|
+
}, i))
|
|
2073
|
+
})
|
|
2074
|
+
}),
|
|
2075
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2076
|
+
className: "mt-16 flex flex-col items-start gap-4 md:col-span-2 md:row-start-3 md:mt-24 md:grid\n md:grid-cols-[auto_min-content] md:items-end md:gap-8",
|
|
2077
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
2078
|
+
className: "text-xs wrap-break-word text-login-100",
|
|
2079
|
+
children: [
|
|
2080
|
+
"Copyright © ",
|
|
2081
|
+
year,
|
|
2082
|
+
" ",
|
|
2083
|
+
t(copyright, lang)
|
|
2084
|
+
]
|
|
2085
|
+
}), version && /* @__PURE__ */ jsx(VersionTag, {
|
|
2086
|
+
version: version.tag,
|
|
2087
|
+
url: version.href
|
|
2088
|
+
})]
|
|
2089
|
+
})
|
|
2090
|
+
]
|
|
2091
|
+
})
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
//#endregion
|
|
2095
|
+
//#region src/components/footer/loginContent.tsx
|
|
2096
|
+
const INSTAGRAM_PATH = "M512 960Q408 960 375.0 959.5Q342 959 301 957Q260 955 230.5 949.0Q201 943 177 933Q151 923 129.0 909.0Q107 895 86 874Q65 853 51.0 831.0Q37 809 27 783Q17 759 11.0 729.5Q5 700 3 659Q1 618 0.5 585.0Q0 552 0 448Q0 344 0.5 311.0Q1 278 3 237Q5 196 11.0 166.5Q17 137 27 113Q37 87 51.0 65.0Q65 43 86 22Q107 1 129.0 -13.0Q151 -27 177 -37Q201 -47 230.5 -53.0Q260 -59 301 -61Q342 -63 375.0 -63.5Q408 -64 512 -64Q616 -64 649.0 -63.5Q682 -63 723 -61Q764 -59 793.5 -53.0Q823 -47 847 -37Q873 -27 895.0 -13.0Q917 1 938 22Q959 43 973.0 65.0Q987 87 997 113Q1007 137 1013.0 166.5Q1019 196 1021 237Q1023 278 1023.5 311.0Q1024 344 1024 448Q1024 552 1023.5 585.0Q1023 618 1021 659Q1019 700 1013.0 729.5Q1007 759 997 783Q987 809 973.0 831.0Q959 853 938 874Q917 895 895.0 909.0Q873 923 847 933Q823 943 793.5 949.0Q764 955 723 957Q682 959 649.0 959.5Q616 960 512 960ZM512 868Q614 868 646.0 867.5Q678 867 719 865Q756 863 778.0 857.5Q800 852 814 847Q832 840 845.5 831.0Q859 822 873 809Q886 795 895.0 781.5Q904 768 911 750Q916 736 921.5 714.0Q927 692 929 655Q931 614 931.5 582.5Q932 551 932 448Q932 345 931.0 313.5Q930 282 929 241Q927 204 921.5 182.0Q916 160 911 146Q903 128 894.5 114.5Q886 101 872 87Q859 74 845.0 65.0Q831 56 813 49Q800 44 777.5 38.5Q755 33 718 31Q677 29 645.0 28.5Q613 28 511 28Q408 28 376.0 29.0Q344 30 303 31Q266 33 243.5 38.5Q221 44 208 49Q190 57 176.5 65.5Q163 74 149 88Q136 101 126.5 115.0Q117 129 111 147Q105 160 100.0 182.5Q95 205 93 242Q91 282 90.5 314.0Q90 346 90 449Q90 551 90.5 583.0Q91 615 93 656Q95 693 100.0 715.5Q105 738 111 751Q117 770 126.5 783.5Q136 797 149 810Q163 824 176.5 833.0Q190 842 208 849Q221 854 243.0 859.5Q265 865 303 867Q344 868 375.5 868.5Q407 869 510 869ZM512 711Q458 711 410 690Q362 670 326.0 634.0Q290 598 270 550Q249 502 249 448Q249 394 270 346Q290 298 326.0 262.0Q362 226 410 206Q458 185 512 185Q566 185 614 206Q662 226 698.0 262.0Q734 298 754 346Q775 394 775 448Q775 502 754 550Q734 598 698.0 634.0Q662 670 614 690Q566 711 512 711ZM512 277Q441 277 391.0 327.0Q341 377 341 448Q341 519 391.0 569.0Q441 619 512 619Q583 619 633.0 569.0Q683 519 683 448Q683 377 633.0 327.0Q583 277 512 277ZM847 721Q847 696 829.0 678.0Q811 660 785 660Q760 660 742.0 678.0Q724 696 724 721Q724 747 742.0 765.0Q760 783 785 783Q811 783 829.0 765.0Q847 747 847 721Z";
|
|
2097
|
+
function InstagramIcon({ size = 24 }) {
|
|
2098
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
2099
|
+
className: "relative block",
|
|
2100
|
+
style: {
|
|
2101
|
+
width: size,
|
|
2102
|
+
height: size
|
|
2103
|
+
},
|
|
2104
|
+
children: [/* @__PURE__ */ jsx("svg", {
|
|
2105
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2106
|
+
viewBox: "0 0 1024 1024",
|
|
2107
|
+
width: size,
|
|
2108
|
+
height: size,
|
|
2109
|
+
"aria-hidden": "true",
|
|
2110
|
+
className: "absolute inset-0 transition-opacity duration-200 opacity-100 group-hover:opacity-0",
|
|
2111
|
+
children: /* @__PURE__ */ jsx("g", {
|
|
2112
|
+
transform: "translate(0 960) scale(1 -1)",
|
|
2113
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
2114
|
+
fill: "currentColor",
|
|
2115
|
+
d: INSTAGRAM_PATH
|
|
2116
|
+
})
|
|
2117
|
+
})
|
|
2118
|
+
}), /* @__PURE__ */ jsxs("svg", {
|
|
2119
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2120
|
+
viewBox: "0 0 1024 1024",
|
|
2121
|
+
width: size,
|
|
2122
|
+
height: size,
|
|
2123
|
+
"aria-hidden": "true",
|
|
2124
|
+
className: "absolute inset-0 transition-opacity duration-200 opacity-0 group-hover:opacity-100",
|
|
2125
|
+
children: [/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", {
|
|
2126
|
+
id: "ig-grad",
|
|
2127
|
+
x1: "0%",
|
|
2128
|
+
y1: "100%",
|
|
2129
|
+
x2: "100%",
|
|
2130
|
+
y2: "0%",
|
|
2131
|
+
children: [
|
|
2132
|
+
/* @__PURE__ */ jsx("stop", {
|
|
2133
|
+
offset: "0%",
|
|
2134
|
+
stopColor: "#fff695"
|
|
2135
|
+
}),
|
|
2136
|
+
/* @__PURE__ */ jsx("stop", {
|
|
2137
|
+
offset: "45%",
|
|
2138
|
+
stopColor: "#ff5445"
|
|
2139
|
+
}),
|
|
2140
|
+
/* @__PURE__ */ jsx("stop", {
|
|
2141
|
+
offset: "60%",
|
|
2142
|
+
stopColor: "#ff37c0"
|
|
2143
|
+
}),
|
|
2144
|
+
/* @__PURE__ */ jsx("stop", {
|
|
2145
|
+
offset: "90%",
|
|
2146
|
+
stopColor: "#3d6dff"
|
|
2147
|
+
})
|
|
2148
|
+
]
|
|
2149
|
+
}) }), /* @__PURE__ */ jsx("g", {
|
|
2150
|
+
transform: "translate(0 960) scale(1 -1)",
|
|
2151
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
2152
|
+
fill: "url(#ig-grad)",
|
|
2153
|
+
d: INSTAGRAM_PATH
|
|
2154
|
+
})
|
|
2155
|
+
})]
|
|
2156
|
+
})]
|
|
2157
|
+
});
|
|
2158
|
+
}
|
|
2159
|
+
const loginAddress = {
|
|
2160
|
+
heading: {
|
|
2161
|
+
no: "Adresse",
|
|
2162
|
+
en: "Address"
|
|
2163
|
+
},
|
|
2164
|
+
items: [
|
|
2165
|
+
{ label: "Teknologivegen 22" },
|
|
2166
|
+
{ label: {
|
|
2167
|
+
no: "Bygg A, rom 155",
|
|
2168
|
+
en: "Building A, room 155"
|
|
2169
|
+
} },
|
|
2170
|
+
{ label: "2815 GJØVIK" }
|
|
2171
|
+
]
|
|
2172
|
+
};
|
|
2173
|
+
const loginEmail = (email) => ({
|
|
2174
|
+
heading: {
|
|
2175
|
+
no: "E-post",
|
|
2176
|
+
en: "Email"
|
|
2177
|
+
},
|
|
2178
|
+
items: [{
|
|
2179
|
+
label: email,
|
|
2180
|
+
href: `mailto:${email}`
|
|
2181
|
+
}]
|
|
2182
|
+
});
|
|
2183
|
+
const loginCopyright = {
|
|
2184
|
+
no: "Login - Linjeforeningen for IT, NO 811 940 372",
|
|
2185
|
+
en: "Login - Association for IT, NO 811 940 372"
|
|
2186
|
+
};
|
|
2187
|
+
const loginSponsor = { label: {
|
|
2188
|
+
no: "Hovedsamarbeidspartner",
|
|
2189
|
+
en: "Main partner"
|
|
2190
|
+
} };
|
|
2191
|
+
const loginSocialLinks = [
|
|
2192
|
+
{
|
|
2193
|
+
title: "Discord",
|
|
2194
|
+
href: "https://discord.gg/login-ntnu",
|
|
2195
|
+
icon: /* @__PURE__ */ jsx(Discord, { size: 24 }),
|
|
2196
|
+
hoverClass: "hover:text-[#6571fd]"
|
|
2197
|
+
},
|
|
2198
|
+
{
|
|
2199
|
+
title: "Instagram",
|
|
2200
|
+
href: "https://www.instagram.com/login_linjeforening/",
|
|
2201
|
+
icon: /* @__PURE__ */ jsx(InstagramIcon, { size: 24 })
|
|
2202
|
+
},
|
|
2203
|
+
{
|
|
2204
|
+
title: "Facebook",
|
|
2205
|
+
href: "https://facebook.com/LogNTNU",
|
|
2206
|
+
icon: /* @__PURE__ */ jsx(Facebook, { size: 24 }),
|
|
2207
|
+
hoverClass: "hover:text-[#2c87ff]"
|
|
2208
|
+
},
|
|
2209
|
+
{
|
|
2210
|
+
title: "LinkedIn",
|
|
2211
|
+
href: "https://www.linkedin.com/company/linjeforeningen-login/about",
|
|
2212
|
+
icon: /* @__PURE__ */ jsx(Linkedin, { size: 24 }),
|
|
2213
|
+
hoverClass: "hover:text-[#1a7bdd]"
|
|
2214
|
+
},
|
|
2215
|
+
{
|
|
2216
|
+
title: "GitHub",
|
|
2217
|
+
href: "https://github.com/login-linjeforeningen-for-it",
|
|
2218
|
+
icon: /* @__PURE__ */ jsx(Github, { size: 24 }),
|
|
2219
|
+
hoverClass: "hover:text-white"
|
|
2220
|
+
},
|
|
2221
|
+
{
|
|
2222
|
+
title: "Wiki",
|
|
2223
|
+
href: "https://outline.login.no/s/doc",
|
|
2224
|
+
icon: /* @__PURE__ */ jsx(Wikijs, { size: 24 }),
|
|
2225
|
+
hoverClass: "hover:text-login-50"
|
|
2226
|
+
}
|
|
2227
|
+
];
|
|
2228
|
+
//#endregion
|
|
2229
|
+
//#region src/components/container/page.tsx
|
|
2230
|
+
function PageContainer({ title, children, className, innerClassName }) {
|
|
2231
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2232
|
+
className: `w-full page-container ${className}`,
|
|
2233
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
2234
|
+
className: `flex flex-col col-start-3 ${innerClassName}`,
|
|
2235
|
+
children: [/* @__PURE__ */ jsx("h1", {
|
|
2236
|
+
className: "heading",
|
|
2237
|
+
children: title
|
|
2238
|
+
}), children]
|
|
2239
|
+
})
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
//#endregion
|
|
2243
|
+
//#region src/components/container/highlight.tsx
|
|
2244
|
+
function Highlight({ children, className }) {
|
|
2245
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2246
|
+
className: `highlighted-section ${className ?? ""}`,
|
|
2247
|
+
children
|
|
2248
|
+
});
|
|
2249
|
+
}
|
|
2250
|
+
//#endregion
|
|
2251
|
+
//#region src/components/container/leftBarPanel.tsx
|
|
2252
|
+
function LeftBarPanel({ color, children, className = "" }) {
|
|
2253
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2254
|
+
className: `bg-login-500/50 border border-login-500/30 border-l-2 rounded-sm ${color} ${className}`,
|
|
2255
|
+
children
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2258
|
+
//#endregion
|
|
2259
|
+
//#region src/components/container/glassCard.tsx
|
|
2260
|
+
function GlassCard({ children, className = "" }) {
|
|
2261
|
+
return /* @__PURE__ */ jsx("section", {
|
|
2262
|
+
className: `rounded-xl border border-login-500/30 bg-login-800 ${className}`,
|
|
2263
|
+
children
|
|
2264
|
+
});
|
|
2265
|
+
}
|
|
2266
|
+
//#endregion
|
|
2267
|
+
//#region src/components/container/iconBubble.tsx
|
|
2268
|
+
const tones = {
|
|
2269
|
+
amber: "bg-amber-500/10 text-amber-400",
|
|
2270
|
+
blue: "bg-sky-500/10 text-sky-400",
|
|
2271
|
+
emerald: "bg-emerald-500/10 text-emerald-400",
|
|
2272
|
+
rose: "bg-rose-500/10 text-rose-400",
|
|
2273
|
+
slate: "bg-login-600 text-login-100",
|
|
2274
|
+
violet: "bg-violet-500/10 text-violet-400",
|
|
2275
|
+
orange: "bg-login/10 text-login"
|
|
2276
|
+
};
|
|
2277
|
+
function IconBubble({ icon: Icon, tone = "slate", size = "md" }) {
|
|
2278
|
+
const sizeClass = size === "sm" ? "h-7 w-7" : size === "lg" ? "h-11 w-11" : "h-9 w-9";
|
|
2279
|
+
const iconSize = size === "sm" ? "h-3.5 w-3.5" : size === "lg" ? "h-5 w-5" : "h-4 w-4";
|
|
2280
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2281
|
+
className: `flex shrink-0 items-center justify-center rounded-lg ${sizeClass} ${tones[tone]}`,
|
|
2282
|
+
children: /* @__PURE__ */ jsx(Icon, { className: iconSize })
|
|
2283
|
+
});
|
|
2284
|
+
}
|
|
2285
|
+
//#endregion
|
|
2286
|
+
//#region src/components/container/statCard.tsx
|
|
2287
|
+
function StatCard({ label, value, icon, tone = "slate" }) {
|
|
2288
|
+
return /* @__PURE__ */ jsxs(GlassCard, {
|
|
2289
|
+
className: "p-4",
|
|
2290
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
2291
|
+
className: "mb-3 flex items-center gap-3",
|
|
2292
|
+
children: [/* @__PURE__ */ jsx(IconBubble, {
|
|
2293
|
+
icon,
|
|
2294
|
+
tone
|
|
2295
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2296
|
+
className: "text-sm font-medium text-login-200",
|
|
2297
|
+
children: label
|
|
2298
|
+
})]
|
|
2299
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2300
|
+
className: "truncate text-lg font-semibold text-login-50",
|
|
2301
|
+
title: value,
|
|
2302
|
+
children: value
|
|
2303
|
+
})]
|
|
2304
|
+
});
|
|
2305
|
+
}
|
|
2306
|
+
//#endregion
|
|
2307
|
+
//#region src/components/container/tabs.tsx
|
|
2308
|
+
function Tabs({ tabs, defaultTab, activeTab: controlledTab, onTabChange, children, className = "" }) {
|
|
2309
|
+
const [internalTab, setInternalTab] = useState(defaultTab ?? tabs[0]?.id ?? "");
|
|
2310
|
+
const activeTab = controlledTab ?? internalTab;
|
|
2311
|
+
function handleTabChange(id) {
|
|
2312
|
+
if (!controlledTab) setInternalTab(id);
|
|
2313
|
+
onTabChange?.(id);
|
|
2314
|
+
}
|
|
2315
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2316
|
+
className,
|
|
2317
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2318
|
+
className: "flex gap-1 rounded-md bg-login-500/50 border border-login-500/40 p-1 w-fit",
|
|
2319
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsx("button", {
|
|
2320
|
+
type: "button",
|
|
2321
|
+
onClick: () => handleTabChange(tab.id),
|
|
2322
|
+
className: `
|
|
2323
|
+
px-3 py-1.5 rounded text-sm font-medium transition-all duration-150 cursor-pointer select-none
|
|
2324
|
+
${activeTab === tab.id ? "bg-login text-white shadow-sm" : "text-login-200 hover:text-login-50 hover:bg-login-600"}
|
|
2325
|
+
`,
|
|
2326
|
+
children: tab.label
|
|
2327
|
+
}, tab.id))
|
|
2328
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2329
|
+
className: "mt-3",
|
|
2330
|
+
children
|
|
2331
|
+
})]
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
function TabPanel({ id, activeTab, children }) {
|
|
2335
|
+
if (activeTab !== id) return null;
|
|
2336
|
+
return /* @__PURE__ */ jsx("div", { children });
|
|
2337
|
+
}
|
|
2338
|
+
//#endregion
|
|
2339
|
+
//#region src/components/container/accordion.tsx
|
|
2340
|
+
const GroupContext = createContext(false);
|
|
2341
|
+
function AccordionGroup({ children, className = "" }) {
|
|
2342
|
+
return /* @__PURE__ */ jsx(GroupContext.Provider, {
|
|
2343
|
+
value: true,
|
|
2344
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2345
|
+
className: `rounded-lg border border-login-500/40 overflow-hidden divide-y divide-login-500/25 ${className}`,
|
|
2346
|
+
children
|
|
2347
|
+
})
|
|
2348
|
+
});
|
|
2349
|
+
}
|
|
2350
|
+
function Accordion({ title, children, defaultOpen = false, className = "" }) {
|
|
2351
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
2352
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2353
|
+
className: useContext(GroupContext) ? className : `rounded-lg border border-login-500/40 overflow-hidden ${className}`,
|
|
2354
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
2355
|
+
type: "button",
|
|
2356
|
+
onClick: () => setOpen((o) => !o),
|
|
2357
|
+
className: "flex w-full cursor-pointer items-center justify-between bg-login-800 px-4 py-3 text-left transition-colors duration-150 hover:bg-login-700 select-none",
|
|
2358
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2359
|
+
className: "text-sm font-medium text-login-50",
|
|
2360
|
+
children: title
|
|
2361
|
+
}), /* @__PURE__ */ jsx(ChevronDown, {
|
|
2362
|
+
size: 16,
|
|
2363
|
+
className: `shrink-0 text-login-300 transition-transform duration-200 ${open ? "rotate-180" : ""}`
|
|
2364
|
+
})]
|
|
2365
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2366
|
+
className: `overflow-hidden bg-login-900 transition-all duration-200 ${open ? "max-h-[9999px]" : "max-h-0"}`,
|
|
2367
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2368
|
+
className: "px-4 py-3 text-sm text-login-100",
|
|
2369
|
+
children
|
|
2370
|
+
})
|
|
2371
|
+
})]
|
|
2372
|
+
});
|
|
2373
|
+
}
|
|
2374
|
+
//#endregion
|
|
2375
|
+
//#region src/components/container/pulseDot.tsx
|
|
2376
|
+
const variantColor = {
|
|
2377
|
+
online: "bg-green-500",
|
|
2378
|
+
offline: "bg-red-500",
|
|
2379
|
+
warning: "bg-login",
|
|
2380
|
+
unknown: "bg-login-400"
|
|
2381
|
+
};
|
|
2382
|
+
const sizeClass = {
|
|
2383
|
+
sm: "w-1.5 h-1.5",
|
|
2384
|
+
md: "w-2 h-2",
|
|
2385
|
+
lg: "w-3 h-3"
|
|
2386
|
+
};
|
|
2387
|
+
function PulseDot({ variant = "online", size = "md" }) {
|
|
2388
|
+
const color = variantColor[variant];
|
|
2389
|
+
const dotSize = sizeClass[size];
|
|
2390
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2391
|
+
className: `relative grid place-items-center ${dotSize}`,
|
|
2392
|
+
children: [/* @__PURE__ */ jsx("span", { className: `absolute inline-flex h-full w-full rounded-full ${color} opacity-50 animate-ping` }), /* @__PURE__ */ jsx("span", { className: `relative inline-flex rounded-full ${dotSize} ${color}` })]
|
|
2393
|
+
});
|
|
2394
|
+
}
|
|
2395
|
+
//#endregion
|
|
2396
|
+
//#region src/components/login/loginPage.tsx
|
|
2397
|
+
function LoginPage({ title, description, redirectPath, version, btg, handleSubmit, guestRedirectPath, guestText }) {
|
|
2398
|
+
return /* @__PURE__ */ jsx("main", {
|
|
2399
|
+
className: "w-full h-full flex items-center justify-center bg-login-800 p-8",
|
|
2400
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
2401
|
+
className: "flex flex-col justify-center items-center bg-login-600 px-4 py-12 rounded-xl w-full max-w-md gap-4 md:gap-6",
|
|
2402
|
+
children: [
|
|
2403
|
+
/* @__PURE__ */ jsx("div", {
|
|
2404
|
+
className: "relative aspect-3/1 w-full",
|
|
2405
|
+
children: /* @__PURE__ */ jsx(Logo, { className: "object-contain px-6 sm:px-12" })
|
|
2406
|
+
}),
|
|
2407
|
+
/* @__PURE__ */ jsxs("h1", {
|
|
2408
|
+
className: "text-3xl font-extrabold text-login text-center tracking-tight",
|
|
2409
|
+
children: [
|
|
2410
|
+
title,
|
|
2411
|
+
" ",
|
|
2412
|
+
btg ? " - Break the Glass" : ""
|
|
2413
|
+
]
|
|
2414
|
+
}),
|
|
2415
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
2416
|
+
className: "text-center font-medium text-lg mb-2 max-w-xs",
|
|
2417
|
+
children: description
|
|
2418
|
+
}),
|
|
2419
|
+
btg ? /* @__PURE__ */ jsxs("form", {
|
|
2420
|
+
className: "w-full flex flex-col gap-3 max-w-xs",
|
|
2421
|
+
onSubmit: (e) => {
|
|
2422
|
+
e.preventDefault();
|
|
2423
|
+
handleSubmit?.(new FormData(e.currentTarget));
|
|
2424
|
+
e.currentTarget.reset();
|
|
2425
|
+
},
|
|
2426
|
+
children: [
|
|
2427
|
+
/* @__PURE__ */ jsx("input", {
|
|
2428
|
+
type: "text",
|
|
2429
|
+
name: "name",
|
|
2430
|
+
placeholder: "Name",
|
|
2431
|
+
className: "py-2 px-3 rounded bg-login-900 font-medium focus:outline-none",
|
|
2432
|
+
required: true
|
|
2433
|
+
}),
|
|
2434
|
+
/* @__PURE__ */ jsx("input", {
|
|
2435
|
+
type: "password",
|
|
2436
|
+
name: "token",
|
|
2437
|
+
placeholder: "Token",
|
|
2438
|
+
className: "py-2 px-3 rounded bg-login-900 font-medium focus:outline-none",
|
|
2439
|
+
required: true
|
|
2440
|
+
}),
|
|
2441
|
+
/* @__PURE__ */ jsx("button", {
|
|
2442
|
+
type: "submit",
|
|
2443
|
+
className: "py-2 px-4 rounded-xl bg-login font-bold text-lg hover:bg-login/80 transition-all duration-200 mt-2",
|
|
2444
|
+
children: "Login"
|
|
2445
|
+
})
|
|
2446
|
+
]
|
|
2447
|
+
}) : /* @__PURE__ */ jsxs(Link, {
|
|
2448
|
+
href: redirectPath,
|
|
2449
|
+
className: `
|
|
2450
|
+
flex items-center justify-center gap-2 w-full
|
|
2451
|
+
max-w-xs py-3 px-6 rounded-xl bg-login font-bold
|
|
2452
|
+
text-lg hover:bg-login/80 transition-all
|
|
2453
|
+
duration-200 mb-2 mt-2 cursor-pointer
|
|
2454
|
+
`,
|
|
2455
|
+
children: ["Login", /* @__PURE__ */ jsx(LogIn, { className: "w-6 h-6" })]
|
|
2456
|
+
}),
|
|
2457
|
+
guestRedirectPath && /* @__PURE__ */ jsx(Link, {
|
|
2458
|
+
href: guestRedirectPath,
|
|
2459
|
+
className: "text-sm font-semibold cursor-pointer opacity-50",
|
|
2460
|
+
children: guestText || "Continue as guest"
|
|
2461
|
+
}),
|
|
2462
|
+
/* @__PURE__ */ jsxs("span", {
|
|
2463
|
+
className: "text-sm mt-2",
|
|
2464
|
+
children: ["v", version]
|
|
2465
|
+
})
|
|
2466
|
+
]
|
|
2467
|
+
})
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
//#endregion
|
|
2471
|
+
//#region src/components/toast/toastItem.tsx
|
|
2472
|
+
function ToastItem({ toast, index, expanded, onRemove, onHeight, offset, frontHeight }) {
|
|
2473
|
+
const [mounted, setMounted] = useState(false);
|
|
2474
|
+
const ref = useRef(null);
|
|
2475
|
+
useEffect(() => {
|
|
2476
|
+
requestAnimationFrame(() => setMounted(true));
|
|
2477
|
+
}, []);
|
|
2478
|
+
useLayoutEffect(() => {
|
|
2479
|
+
if (ref.current) onHeight(toast.id, ref.current.offsetHeight);
|
|
2480
|
+
}, [
|
|
2481
|
+
toast.message,
|
|
2482
|
+
onHeight,
|
|
2483
|
+
toast.id,
|
|
2484
|
+
expanded
|
|
2485
|
+
]);
|
|
2486
|
+
const isVisible = mounted && !toast.exiting;
|
|
2487
|
+
const isFront = index === 0;
|
|
2488
|
+
const collapsedOffset = index * 10 + (index > 0 ? frontHeight - 60 : 0);
|
|
2489
|
+
return /* @__PURE__ */ jsx("li", {
|
|
2490
|
+
ref,
|
|
2491
|
+
className: "absolute bottom-0 right-0 w-full transition-all duration-300 ease-out pointer-events-auto",
|
|
2492
|
+
style: {
|
|
2493
|
+
transform: isVisible ? `translateY(${expanded ? -offset : -collapsedOffset}px) scale(${expanded ? 1 : 1 - index * .05})` : "translateY(20px) scale(0.9)",
|
|
2494
|
+
opacity: isVisible ? 1 : 0,
|
|
2495
|
+
zIndex: toast.id
|
|
2496
|
+
},
|
|
2497
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
2498
|
+
className: "flex items-center space-x-4 rounded-lg p-4 shadow-lg border-2 border-login-400 bg-login-700",
|
|
2499
|
+
children: [
|
|
2500
|
+
/* @__PURE__ */ jsx("div", {
|
|
2501
|
+
className: "shrink-0",
|
|
2502
|
+
children: Icon(toast.type)
|
|
2503
|
+
}),
|
|
2504
|
+
/* @__PURE__ */ jsx("p", {
|
|
2505
|
+
className: `flex-1 text-sm font-semibold text-login-800 dark:text-login-100 min-w-0
|
|
2506
|
+
${!expanded && !isFront ? "truncate" : ""}`,
|
|
2507
|
+
children: toast.message
|
|
2508
|
+
}),
|
|
2509
|
+
/* @__PURE__ */ jsx("button", {
|
|
2510
|
+
onClick: onRemove,
|
|
2511
|
+
className: "hover:text-login-200 text-login-400",
|
|
2512
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
|
|
2513
|
+
})
|
|
2514
|
+
]
|
|
2515
|
+
})
|
|
2516
|
+
});
|
|
2517
|
+
}
|
|
2518
|
+
function Icon(type) {
|
|
2519
|
+
switch (type) {
|
|
2520
|
+
case "info": return /* @__PURE__ */ jsx(Info, { className: "h-6 w-6 text-blue-500" });
|
|
2521
|
+
case "success": return /* @__PURE__ */ jsx(CheckCircle, { className: "h-6 w-6 text-green-500" });
|
|
2522
|
+
case "warning": return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-6 w-6 text-yellow-500" });
|
|
2523
|
+
case "error": return /* @__PURE__ */ jsx(AlertCircle, { className: "h-6 w-6 text-red-500" });
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
//#endregion
|
|
2527
|
+
//#region src/components/toast/toaster.tsx
|
|
2528
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2529
|
+
let idCounter = 0;
|
|
2530
|
+
function toast(message, type, duration = 4e3) {
|
|
2531
|
+
const id = ++idCounter;
|
|
2532
|
+
listeners.forEach((listener) => listener({
|
|
2533
|
+
id,
|
|
2534
|
+
message,
|
|
2535
|
+
type,
|
|
2536
|
+
expiresAt: Date.now() + duration
|
|
2537
|
+
}));
|
|
2538
|
+
}
|
|
2539
|
+
toast.info = (message, duration) => toast(message, "info", duration);
|
|
2540
|
+
toast.success = (message, duration) => toast(message, "success", duration);
|
|
2541
|
+
toast.warning = (message, duration) => toast(message, "warning", duration);
|
|
2542
|
+
toast.error = (message, duration) => toast(message, "error", duration);
|
|
2543
|
+
function Toaster() {
|
|
2544
|
+
const [toasts, setToasts] = useState([]);
|
|
2545
|
+
const [expanded, setExpanded] = useState(false);
|
|
2546
|
+
const [heights, setHeights] = useState({});
|
|
2547
|
+
useEffect(() => {
|
|
2548
|
+
function addToast(toast) {
|
|
2549
|
+
setToasts((prev) => [toast, ...prev]);
|
|
2550
|
+
}
|
|
2551
|
+
listeners.add(addToast);
|
|
2552
|
+
return () => {
|
|
2553
|
+
listeners.delete(addToast);
|
|
2554
|
+
};
|
|
2555
|
+
}, []);
|
|
2556
|
+
useEffect(() => {
|
|
2557
|
+
const now = Date.now();
|
|
2558
|
+
setToasts((prev) => prev.map((toast) => {
|
|
2559
|
+
if (expanded) return {
|
|
2560
|
+
...toast,
|
|
2561
|
+
pausedAt: toast.pausedAt || now
|
|
2562
|
+
};
|
|
2563
|
+
if (!toast.pausedAt) return toast;
|
|
2564
|
+
return {
|
|
2565
|
+
...toast,
|
|
2566
|
+
expiresAt: toast.expiresAt + (now - toast.pausedAt),
|
|
2567
|
+
pausedAt: void 0
|
|
2568
|
+
};
|
|
2569
|
+
}));
|
|
2570
|
+
}, [expanded]);
|
|
2571
|
+
function removeToast(id) {
|
|
2572
|
+
setToasts((prev) => prev.map((toast) => toast.id === id ? {
|
|
2573
|
+
...toast,
|
|
2574
|
+
exiting: true
|
|
2575
|
+
} : toast));
|
|
2576
|
+
setTimeout(() => {
|
|
2577
|
+
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
|
2578
|
+
}, 300);
|
|
2579
|
+
}
|
|
2580
|
+
useEffect(() => {
|
|
2581
|
+
const timer = setInterval(() => {
|
|
2582
|
+
if (expanded) return;
|
|
2583
|
+
const now = Date.now();
|
|
2584
|
+
setToasts((prev) => {
|
|
2585
|
+
const toastsToExit = prev.filter((toast) => !toast.exiting && !toast.pausedAt && toast.expiresAt <= now);
|
|
2586
|
+
if (toastsToExit.length === 0) return prev;
|
|
2587
|
+
toastsToExit.forEach((toast) => {
|
|
2588
|
+
setTimeout(() => {
|
|
2589
|
+
setToasts((current) => current.filter((item) => item.id !== toast.id));
|
|
2590
|
+
}, 300);
|
|
2591
|
+
});
|
|
2592
|
+
return prev.map((toast) => toastsToExit.find((exitToast) => exitToast.id === toast.id) ? {
|
|
2593
|
+
...toast,
|
|
2594
|
+
exiting: true
|
|
2595
|
+
} : toast);
|
|
2596
|
+
});
|
|
2597
|
+
}, 100);
|
|
2598
|
+
return () => clearInterval(timer);
|
|
2599
|
+
}, [expanded]);
|
|
2600
|
+
function onHeight(id, height) {
|
|
2601
|
+
setHeights((prev) => {
|
|
2602
|
+
if (prev[id] === height) return prev;
|
|
2603
|
+
return {
|
|
2604
|
+
...prev,
|
|
2605
|
+
[id]: height
|
|
2606
|
+
};
|
|
2607
|
+
});
|
|
2608
|
+
}
|
|
2609
|
+
const visibleToasts = toasts.slice(0, expanded ? 10 : 3);
|
|
2610
|
+
const frontHeight = heights[visibleToasts[0]?.id] || 60;
|
|
2611
|
+
const offsets = useMemo(() => {
|
|
2612
|
+
let currentOffset = 0;
|
|
2613
|
+
return visibleToasts.map((toast) => {
|
|
2614
|
+
const height = heights[toast.id] || 60;
|
|
2615
|
+
const offset = currentOffset;
|
|
2616
|
+
currentOffset += height + 16;
|
|
2617
|
+
return offset;
|
|
2618
|
+
});
|
|
2619
|
+
}, [visibleToasts, heights]);
|
|
2620
|
+
const totalHeight = offsets.length > 0 ? offsets[offsets.length - 1] + (heights[visibleToasts[visibleToasts.length - 1]?.id] || 60) : 0;
|
|
2621
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
2622
|
+
className: `fixed bottom-4 right-4 z-9999 w-full max-w-sm flex flex-col items-end transition-all duration-300 ease-out
|
|
2623
|
+
${expanded ? "pointer-events-auto" : "pointer-events-none"}`,
|
|
2624
|
+
style: { height: expanded ? totalHeight + "px" : "auto" },
|
|
2625
|
+
onMouseEnter: () => setExpanded(true),
|
|
2626
|
+
onMouseLeave: () => setExpanded(false),
|
|
2627
|
+
children: visibleToasts.map((toast, index) => /* @__PURE__ */ jsx(ToastItem, {
|
|
2628
|
+
toast,
|
|
2629
|
+
index,
|
|
2630
|
+
expanded,
|
|
2631
|
+
onRemove: () => removeToast(toast.id),
|
|
2632
|
+
onHeight,
|
|
2633
|
+
offset: offsets[index],
|
|
2634
|
+
frontHeight
|
|
2635
|
+
}, toast.id))
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
//#endregion
|
|
2639
|
+
//#region src/components/buttons/button.tsx
|
|
2640
|
+
const variants = {
|
|
2641
|
+
primary: "bg-login text-white hover:brightness-110",
|
|
2642
|
+
secondary: "bg-login-500 text-login-50 hover:bg-login-400",
|
|
2643
|
+
warning: "bg-yellow-500 text-black hover:brightness-110",
|
|
2644
|
+
danger: "bg-red-600 text-white hover:brightness-110",
|
|
2645
|
+
success: "bg-green-600 text-white hover:brightness-110",
|
|
2646
|
+
info: "bg-blue-600 text-white hover:brightness-110"
|
|
2647
|
+
};
|
|
2648
|
+
const base = "cursor-pointer px-4 rounded-md h-9 flex items-center justify-center gap-2 select-none text-sm font-medium transition-all duration-150 w-fit";
|
|
2649
|
+
const disabledCls = "opacity-40 cursor-not-allowed pointer-events-none";
|
|
2650
|
+
const iconWrap = (icon) => icon ? /* @__PURE__ */ jsx("span", {
|
|
2651
|
+
className: "[&>svg]:w-4 [&>svg]:h-4 flex items-center",
|
|
2652
|
+
children: icon
|
|
2653
|
+
}) : null;
|
|
2654
|
+
function Button({ text, className, icon, path, variant = "primary", type, onClick, disabled }) {
|
|
2655
|
+
const color = variants[variant];
|
|
2656
|
+
const cls = `${base} ${color} ${disabled ? disabledCls : ""} ${className || ""}`;
|
|
2657
|
+
if (!path) return /* @__PURE__ */ jsxs("button", {
|
|
2658
|
+
type: type || "button",
|
|
2659
|
+
disabled,
|
|
2660
|
+
onClick,
|
|
2661
|
+
"aria-label": text,
|
|
2662
|
+
className: cls,
|
|
2663
|
+
children: [iconWrap(icon), text]
|
|
2664
|
+
});
|
|
2665
|
+
if (disabled) return /* @__PURE__ */ jsxs("div", {
|
|
2666
|
+
className: cls,
|
|
2667
|
+
children: [iconWrap(icon), text]
|
|
2668
|
+
});
|
|
2669
|
+
return /* @__PURE__ */ jsxs(Link, {
|
|
2670
|
+
href: path,
|
|
2671
|
+
className: `${base} ${color} ${className || ""}`,
|
|
2672
|
+
children: [iconWrap(icon), text]
|
|
2673
|
+
});
|
|
2674
|
+
}
|
|
2675
|
+
//#endregion
|
|
2676
|
+
//#region src/components/alert/alert.tsx
|
|
2677
|
+
const styles = {
|
|
2678
|
+
warning: {
|
|
2679
|
+
color: "border-l-red-500",
|
|
2680
|
+
iconClass: "w-4 h-4 shrink-0 stroke-red-400 mr-3 mt-0.5",
|
|
2681
|
+
Icon: CircleAlert
|
|
2682
|
+
},
|
|
2683
|
+
info: {
|
|
2684
|
+
color: "border-l-blue-500",
|
|
2685
|
+
iconClass: "w-4 h-4 shrink-0 stroke-blue-400 mr-3 mt-0.5",
|
|
2686
|
+
Icon: Info
|
|
2687
|
+
}
|
|
2688
|
+
};
|
|
2689
|
+
function Alert({ children, variant = "warning", className = "" }) {
|
|
2690
|
+
const { color, iconClass, Icon } = styles[variant] ?? styles.warning;
|
|
2691
|
+
return /* @__PURE__ */ jsxs(LeftBarPanel, {
|
|
2692
|
+
color,
|
|
2693
|
+
className: `flex items-start px-4 py-3 text-sm text-login-100 ${className}`,
|
|
2694
|
+
children: [/* @__PURE__ */ jsx(Icon, { className: iconClass }), /* @__PURE__ */ jsx("div", {
|
|
2695
|
+
className: "leading-relaxed",
|
|
2696
|
+
children
|
|
2697
|
+
})]
|
|
2698
|
+
});
|
|
2699
|
+
}
|
|
2700
|
+
//#endregion
|
|
2701
|
+
//#region src/components/table/menu.tsx
|
|
2702
|
+
const MenuContext = createContext({});
|
|
2703
|
+
function Menu({ ref, children, anchor, onClose }) {
|
|
2704
|
+
return createPortal(/* @__PURE__ */ jsx("div", {
|
|
2705
|
+
ref,
|
|
2706
|
+
style: {
|
|
2707
|
+
top: anchor.top,
|
|
2708
|
+
right: anchor.right
|
|
2709
|
+
},
|
|
2710
|
+
className: "fixed bg-login-500 border border-login-600 rounded-lg shadow-lg z-9999 w-44",
|
|
2711
|
+
children: /* @__PURE__ */ jsx(MenuContext.Provider, {
|
|
2712
|
+
value: { onClose },
|
|
2713
|
+
children
|
|
2714
|
+
})
|
|
2715
|
+
}), document.body);
|
|
2716
|
+
}
|
|
2717
|
+
function MenuButton({ icon, text, hotKey, onClick, className }) {
|
|
2718
|
+
const { onClose } = useContext(MenuContext);
|
|
2719
|
+
useEffect(() => {
|
|
2720
|
+
if (!hotKey) return;
|
|
2721
|
+
function handleKeyDown(e) {
|
|
2722
|
+
if (e.key.toLowerCase() === hotKey.toLowerCase()) {
|
|
2723
|
+
e.preventDefault();
|
|
2724
|
+
onClick();
|
|
2725
|
+
onClose?.();
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
2729
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2730
|
+
}, [
|
|
2731
|
+
hotKey,
|
|
2732
|
+
onClick,
|
|
2733
|
+
onClose
|
|
2734
|
+
]);
|
|
2735
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
2736
|
+
onClick: () => {
|
|
2737
|
+
onClick();
|
|
2738
|
+
onClose?.();
|
|
2739
|
+
},
|
|
2740
|
+
className: `flex items-center justify-between w-full px-3 py-2 text-sm hover:bg-login-600 cursor-pointer
|
|
2741
|
+
${className || ""}
|
|
2742
|
+
`,
|
|
2743
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
2744
|
+
className: "flex items-center",
|
|
2745
|
+
children: [React.cloneElement(icon, { className: "w-4 h-4 mr-2" }), text]
|
|
2746
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2747
|
+
className: "text-xs opacity-50 font-mono",
|
|
2748
|
+
children: hotKey
|
|
2749
|
+
})]
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2752
|
+
//#endregion
|
|
2753
|
+
//#region src/components/table/format.ts
|
|
2754
|
+
const nullableTimeKeys = [
|
|
2755
|
+
"date",
|
|
2756
|
+
"last_sent",
|
|
2757
|
+
"time"
|
|
2758
|
+
];
|
|
2759
|
+
const ISODateTimeReg = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/;
|
|
2760
|
+
const ISODateReg = /^\d{4}-\d{2}-\d{2}$/;
|
|
2761
|
+
const ISOTimeReg = /^\d{2}:\d{2}(:\d{2})?$/;
|
|
2762
|
+
const OsloTZ = { timeZone: "Europe/Oslo" };
|
|
2763
|
+
const OsloTime = {
|
|
2764
|
+
...OsloTZ,
|
|
2765
|
+
hour: "2-digit",
|
|
2766
|
+
minute: "2-digit"
|
|
2767
|
+
};
|
|
2768
|
+
const OsloDateTime = {
|
|
2769
|
+
...OsloTime,
|
|
2770
|
+
year: "numeric",
|
|
2771
|
+
month: "2-digit",
|
|
2772
|
+
day: "2-digit"
|
|
2773
|
+
};
|
|
2774
|
+
function formatValue(key, value) {
|
|
2775
|
+
if (nullableTimeKeys.includes(key) && !value) return "Never";
|
|
2776
|
+
if (typeof value === "string") {
|
|
2777
|
+
if (ISODateTimeReg.test(value)) return new Date(value).toLocaleString("nb-NO", OsloDateTime);
|
|
2778
|
+
if (ISODateReg.test(value)) return new Date(value).toLocaleDateString("nb-NO", OsloTZ);
|
|
2779
|
+
if (ISOTimeReg.test(value)) return (/* @__PURE__ */ new Date(`1970-01-01T${value}`)).toLocaleTimeString("nb-NO", OsloTime);
|
|
2780
|
+
}
|
|
2781
|
+
if (key.includes("capacity")) return value === 0 ? "Unlimited" : value;
|
|
2782
|
+
return value;
|
|
2783
|
+
}
|
|
2784
|
+
//#endregion
|
|
2785
|
+
//#region src/components/table/body.tsx
|
|
2786
|
+
function Body({ list, columns, menuItems, redirectPath, variant = "default", idKey }) {
|
|
2787
|
+
const [openMenuId, setOpenMenuId] = useState(null);
|
|
2788
|
+
const [anchor, setAnchor] = useState(null);
|
|
2789
|
+
const router = useRouter();
|
|
2790
|
+
const menuRef = useRef(null);
|
|
2791
|
+
const tbodyRef = useRef(null);
|
|
2792
|
+
const menuWasOpenOnMouseDown = useRef(false);
|
|
2793
|
+
useClickOutside(menuRef, () => setOpenMenuId(null));
|
|
2794
|
+
useEffect(() => {
|
|
2795
|
+
const el = tbodyRef.current;
|
|
2796
|
+
if (!el) return;
|
|
2797
|
+
const close = () => setOpenMenuId(null);
|
|
2798
|
+
el.addEventListener("scroll", close);
|
|
2799
|
+
return () => el.removeEventListener("scroll", close);
|
|
2800
|
+
}, []);
|
|
2801
|
+
return /* @__PURE__ */ jsx("tbody", {
|
|
2802
|
+
ref: tbodyRef,
|
|
2803
|
+
className: `
|
|
2804
|
+
block overflow-y-auto flex-1 min-h-0 divide-y
|
|
2805
|
+
${variant === "default" ? "bg-login-800 divide-login-600/25" : "bg-transparent divide-login-600/20"}
|
|
2806
|
+
`,
|
|
2807
|
+
children: list.map((item, index) => {
|
|
2808
|
+
const itemRecord = item;
|
|
2809
|
+
let id = "";
|
|
2810
|
+
if (idKey && itemRecord[idKey] !== void 0) id = String(itemRecord[idKey]);
|
|
2811
|
+
else if (itemRecord["id"] !== void 0) id = String(itemRecord["id"]);
|
|
2812
|
+
else {
|
|
2813
|
+
const firstKey = columns[0]?.key || Object.keys(itemRecord)[0];
|
|
2814
|
+
id = String(itemRecord[firstKey]);
|
|
2815
|
+
}
|
|
2816
|
+
const redirectConfig = typeof redirectPath === "object" && redirectPath ? redirectPath : { path: redirectPath };
|
|
2817
|
+
const redirectId = redirectConfig.key ? String(itemRecord[redirectConfig.key]) : id;
|
|
2818
|
+
const menuButtonColors = variant === "minimal" ? {
|
|
2819
|
+
active: "bg-login-600 text-login-100",
|
|
2820
|
+
inactive: "hover:bg-login-600 text-login-200 hover:text-login-100"
|
|
2821
|
+
} : {
|
|
2822
|
+
active: "bg-login-400 text-login-100",
|
|
2823
|
+
inactive: "hover:bg-login-400 text-login-200 hover:text-login-100"
|
|
2824
|
+
};
|
|
2825
|
+
const buttonClass = openMenuId === id ? menuButtonColors.active : menuButtonColors.inactive;
|
|
2826
|
+
return /* @__PURE__ */ jsxs("tr", {
|
|
2827
|
+
className: `
|
|
2828
|
+
flex w-full group/row transition-colors
|
|
2829
|
+
${redirectConfig.path ? "cursor-pointer" : ""}
|
|
2830
|
+
${variant === "default" && redirectConfig.path ? "hover:bg-login-600/80" : ""}
|
|
2831
|
+
${variant === "minimal" ? "hover:bg-login-600/70 border-b border-login-600/20 last:border-0" : ""}
|
|
2832
|
+
`,
|
|
2833
|
+
onMouseDown: () => {
|
|
2834
|
+
menuWasOpenOnMouseDown.current = openMenuId !== null;
|
|
2835
|
+
},
|
|
2836
|
+
onClick: () => {
|
|
2837
|
+
if (menuWasOpenOnMouseDown.current) {
|
|
2838
|
+
menuWasOpenOnMouseDown.current = false;
|
|
2839
|
+
return;
|
|
2840
|
+
}
|
|
2841
|
+
if (redirectConfig.path) if (redirectConfig.path.includes("?")) router.push(`${redirectConfig.path}${redirectId}`);
|
|
2842
|
+
else router.push(`${redirectConfig.path}/${redirectId}`);
|
|
2843
|
+
},
|
|
2844
|
+
onContextMenu: (e) => {
|
|
2845
|
+
e.preventDefault();
|
|
2846
|
+
setAnchor({
|
|
2847
|
+
top: e.clientY,
|
|
2848
|
+
right: window.innerWidth - e.clientX
|
|
2849
|
+
});
|
|
2850
|
+
setOpenMenuId(id);
|
|
2851
|
+
},
|
|
2852
|
+
children: [columns.map((col) => {
|
|
2853
|
+
const value = itemRecord[col.key];
|
|
2854
|
+
let badgeClass = "";
|
|
2855
|
+
if (col.highlight) {
|
|
2856
|
+
const highlightKey = String(value);
|
|
2857
|
+
const colorName = col.highlight[highlightKey] || col.highlight.default;
|
|
2858
|
+
if (colorName) {
|
|
2859
|
+
switch (colorName) {
|
|
2860
|
+
case "green":
|
|
2861
|
+
badgeClass = "bg-green-500/20 text-green-400";
|
|
2862
|
+
break;
|
|
2863
|
+
case "yellow":
|
|
2864
|
+
badgeClass = "bg-yellow-500/20 text-yellow-400";
|
|
2865
|
+
break;
|
|
2866
|
+
case "red":
|
|
2867
|
+
badgeClass = "bg-red-500/20 text-red-400";
|
|
2868
|
+
break;
|
|
2869
|
+
case "blue":
|
|
2870
|
+
badgeClass = "bg-blue-500/20 text-blue-400";
|
|
2871
|
+
break;
|
|
2872
|
+
case "gray":
|
|
2873
|
+
badgeClass = "bg-gray-500/20 text-gray-400";
|
|
2874
|
+
break;
|
|
2875
|
+
}
|
|
2876
|
+
badgeClass += " px-2 py-1 rounded";
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
return /* @__PURE__ */ jsx("td", {
|
|
2880
|
+
className: `
|
|
2881
|
+
flex-1 min-w-0 px-6 py-4 whitespace-nowrap text-sm flex items-center text-login-100
|
|
2882
|
+
${variant === "minimal" ? "px-4! py-2!" : ""}
|
|
2883
|
+
`,
|
|
2884
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2885
|
+
className: "relative w-full min-w-0",
|
|
2886
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
2887
|
+
className: `block max-w-full truncate ${badgeClass}`,
|
|
2888
|
+
children: formatValue(col.key, value)
|
|
2889
|
+
})
|
|
2890
|
+
})
|
|
2891
|
+
}, col.key);
|
|
2892
|
+
}), menuItems && /* @__PURE__ */ jsx("td", {
|
|
2893
|
+
className: "shrink-0 w-16 flex flex-row items-center justify-end p-2 px-4\n whitespace-nowrap text-right text-sm font-medium",
|
|
2894
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
2895
|
+
className: "relative",
|
|
2896
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
2897
|
+
type: "button",
|
|
2898
|
+
className: `p-1.5 rounded flex items-center justify-center transition-colors ${buttonClass}`,
|
|
2899
|
+
onMouseDown: (e) => e.nativeEvent.stopImmediatePropagation(),
|
|
2900
|
+
onClick: (e) => {
|
|
2901
|
+
e.stopPropagation();
|
|
2902
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
2903
|
+
const coords = {
|
|
2904
|
+
top: rect.bottom + 4,
|
|
2905
|
+
right: window.innerWidth - rect.right
|
|
2906
|
+
};
|
|
2907
|
+
setAnchor(openMenuId === id ? null : coords);
|
|
2908
|
+
setOpenMenuId(openMenuId === id ? null : id);
|
|
2909
|
+
},
|
|
2910
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
2911
|
+
className: "text-xl leading-none select-none",
|
|
2912
|
+
children: /* @__PURE__ */ jsx(EllipsisVertical, { className: "h-5 w-5" })
|
|
2913
|
+
})
|
|
2914
|
+
}), openMenuId === id && anchor && /* @__PURE__ */ jsx(Menu, {
|
|
2915
|
+
ref: menuRef,
|
|
2916
|
+
anchor,
|
|
2917
|
+
onClose: () => setOpenMenuId(null),
|
|
2918
|
+
children: menuItems?.(item, id)
|
|
2919
|
+
})]
|
|
2920
|
+
})
|
|
2921
|
+
})]
|
|
2922
|
+
}, index);
|
|
2923
|
+
})
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
//#endregion
|
|
2927
|
+
//#region src/components/table/header.tsx
|
|
2928
|
+
function parseOrder(value) {
|
|
2929
|
+
return value === "asc" || value === "desc" ? value : void 0;
|
|
2930
|
+
}
|
|
2931
|
+
function Header({ columns, hideMenu, variant = "default" }) {
|
|
2932
|
+
const router = useRouter();
|
|
2933
|
+
const pathname = usePathname();
|
|
2934
|
+
const searchParams = useSearchParams();
|
|
2935
|
+
const [column, setColumn] = useState(searchParams.get("column") ?? "");
|
|
2936
|
+
const [order, setOrder] = useState(parseOrder(searchParams.get("order")));
|
|
2937
|
+
useEffect(() => {
|
|
2938
|
+
if (!column || !order) return;
|
|
2939
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
2940
|
+
if (searchParams.get("order") !== order || searchParams.get("column") !== column) {
|
|
2941
|
+
params.set("order", order);
|
|
2942
|
+
params.set("column", column);
|
|
2943
|
+
params.set("page", "1");
|
|
2944
|
+
router.push(`${pathname}?${params.toString()}`);
|
|
2945
|
+
}
|
|
2946
|
+
}, [
|
|
2947
|
+
order,
|
|
2948
|
+
column,
|
|
2949
|
+
pathname,
|
|
2950
|
+
router,
|
|
2951
|
+
searchParams
|
|
2952
|
+
]);
|
|
2953
|
+
function handleChange(key) {
|
|
2954
|
+
setColumn(key);
|
|
2955
|
+
setOrder((prev) => key === column && prev === "asc" ? "desc" : "asc");
|
|
2956
|
+
}
|
|
2957
|
+
return /* @__PURE__ */ jsx("thead", {
|
|
2958
|
+
className: `
|
|
2959
|
+
block w-full
|
|
2960
|
+
${variant === "default" ? "bg-login-700" : "bg-transparent border-b border-login-600"}
|
|
2961
|
+
`,
|
|
2962
|
+
children: /* @__PURE__ */ jsxs("tr", {
|
|
2963
|
+
className: "flex w-full",
|
|
2964
|
+
children: [columns.map((col) => {
|
|
2965
|
+
const key = col.key;
|
|
2966
|
+
const value = col.label || (key.length < 3 ? key.toUpperCase() : `${key[0].toUpperCase()}${key.slice(1).replaceAll("_", " ")}`);
|
|
2967
|
+
return /* @__PURE__ */ jsx("th", {
|
|
2968
|
+
className: `
|
|
2969
|
+
flex-1 min-w-0 px-6 py-3 text-xs font-medium uppercase tracking-wider text-left
|
|
2970
|
+
${variant === "default" ? "text-login-200" : "text-login-100"}
|
|
2971
|
+
${variant === "minimal" ? "px-4!" : ""}
|
|
2972
|
+
`,
|
|
2973
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
2974
|
+
className: "flex w-full min-w-0 flex-row items-center gap-2 group uppercase whitespace-nowrap",
|
|
2975
|
+
onClick: () => handleChange(key),
|
|
2976
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2977
|
+
className: "min-w-0 truncate",
|
|
2978
|
+
children: value
|
|
2979
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2980
|
+
className: "flex flex-col",
|
|
2981
|
+
children: column === key ? order === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4 stroke-login-200 opacity-0 group-hover:opacity-100" })
|
|
2982
|
+
})]
|
|
2983
|
+
})
|
|
2984
|
+
}, key);
|
|
2985
|
+
}), !hideMenu && /* @__PURE__ */ jsx("th", { className: "shrink-0 w-16 px-6 py-3" })]
|
|
2986
|
+
})
|
|
2987
|
+
});
|
|
2988
|
+
}
|
|
2989
|
+
//#endregion
|
|
2990
|
+
//#region src/components/table/table.tsx
|
|
2991
|
+
function Table({ data, columns, menuItems, redirectPath, variant = "default", idKey }) {
|
|
2992
|
+
if (data.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
2993
|
+
className: "p-4 text-center text-login-200",
|
|
2994
|
+
children: "No data found"
|
|
2995
|
+
});
|
|
2996
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2997
|
+
className: `
|
|
2998
|
+
flex-1 flex flex-col min-h-0 overflow-x-auto overflow-y-hidden h-full w-full
|
|
2999
|
+
${variant === "default" ? "bg-login-800 rounded-lg border border-login-600/30" : ""}
|
|
3000
|
+
${variant === "minimal" ? "bg-transparent" : ""}
|
|
3001
|
+
`,
|
|
3002
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
3003
|
+
className: "min-w-full w-max divide-y divide-login-600/30 flex flex-col flex-1 min-h-0",
|
|
3004
|
+
children: [/* @__PURE__ */ jsx(Header, {
|
|
3005
|
+
columns,
|
|
3006
|
+
hideMenu: !menuItems,
|
|
3007
|
+
variant
|
|
3008
|
+
}), /* @__PURE__ */ jsx(Body, {
|
|
3009
|
+
list: data,
|
|
3010
|
+
columns,
|
|
3011
|
+
menuItems,
|
|
3012
|
+
redirectPath,
|
|
3013
|
+
variant,
|
|
3014
|
+
idKey
|
|
3015
|
+
})]
|
|
3016
|
+
})
|
|
3017
|
+
});
|
|
3018
|
+
}
|
|
3019
|
+
//#endregion
|
|
3020
|
+
//#region src/components/table/pagination.tsx
|
|
3021
|
+
function Pagination({ pageSize = 10, totalRows }) {
|
|
3022
|
+
const router = useRouter();
|
|
3023
|
+
const pathname = usePathname();
|
|
3024
|
+
const searchParams = useSearchParams();
|
|
3025
|
+
const rawPage = parseInt(searchParams.get("page") || "1", 10);
|
|
3026
|
+
const [current, setCurrent] = useState(Math.max(1, Number.isNaN(rawPage) ? 1 : rawPage));
|
|
3027
|
+
const totalPages = Math.max(1, Math.ceil(totalRows !== void 0 && pageSize > 0 ? totalRows / pageSize : 1));
|
|
3028
|
+
useEffect(() => {
|
|
3029
|
+
const raw = parseInt(searchParams.get("page") || "1", 10);
|
|
3030
|
+
setCurrent(Math.max(1, Math.min(totalPages, Math.max(1, Number.isNaN(raw) ? 1 : raw))));
|
|
3031
|
+
}, [searchParams, totalPages]);
|
|
3032
|
+
function updateQuery(p) {
|
|
3033
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
3034
|
+
params.set("page", String(p));
|
|
3035
|
+
router.push(`${pathname}?${params.toString()}`);
|
|
3036
|
+
}
|
|
3037
|
+
function goPrevious() {
|
|
3038
|
+
if (current <= 1) return;
|
|
3039
|
+
const next = current - 1;
|
|
3040
|
+
setCurrent(next);
|
|
3041
|
+
updateQuery(next);
|
|
3042
|
+
}
|
|
3043
|
+
function goNext() {
|
|
3044
|
+
if (current >= totalPages) return;
|
|
3045
|
+
const next = current + 1;
|
|
3046
|
+
setCurrent(next);
|
|
3047
|
+
updateQuery(next);
|
|
3048
|
+
}
|
|
3049
|
+
function setPage(p) {
|
|
3050
|
+
if (p === current) return;
|
|
3051
|
+
setCurrent(p);
|
|
3052
|
+
updateQuery(p);
|
|
3053
|
+
}
|
|
3054
|
+
function getPages(curr, total) {
|
|
3055
|
+
const delta = 2;
|
|
3056
|
+
const left = Math.max(1, curr - delta);
|
|
3057
|
+
const right = Math.min(total, curr + delta);
|
|
3058
|
+
const pages = [];
|
|
3059
|
+
if (left > 1) {
|
|
3060
|
+
pages.push(1);
|
|
3061
|
+
if (left > 2) pages.push("...");
|
|
3062
|
+
}
|
|
3063
|
+
for (let i = left; i <= right; i++) pages.push(i);
|
|
3064
|
+
if (right < total) {
|
|
3065
|
+
if (right < total - 1) pages.push("...");
|
|
3066
|
+
pages.push(total);
|
|
3067
|
+
}
|
|
3068
|
+
return pages;
|
|
3069
|
+
}
|
|
3070
|
+
const pages = getPages(current, totalPages);
|
|
3071
|
+
const start = Math.max(1, (current - 1) * pageSize + 1);
|
|
3072
|
+
const end = Math.min(current * pageSize, totalRows !== void 0 ? totalRows : current * pageSize);
|
|
3073
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3074
|
+
className: "flex items-center justify-between w-full pt-4",
|
|
3075
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3076
|
+
className: "text-sm /70",
|
|
3077
|
+
children: totalRows !== void 0 ? totalRows === 0 ? /* @__PURE__ */ jsx("span", { children: "Showing 0 results" }) : /* @__PURE__ */ jsxs("span", { children: [
|
|
3078
|
+
"Showing ",
|
|
3079
|
+
start,
|
|
3080
|
+
" to ",
|
|
3081
|
+
end,
|
|
3082
|
+
" of ",
|
|
3083
|
+
totalRows,
|
|
3084
|
+
" results"
|
|
3085
|
+
] }) : null
|
|
3086
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3087
|
+
className: "flex items-center gap-3",
|
|
3088
|
+
children: [
|
|
3089
|
+
/* @__PURE__ */ jsx("button", {
|
|
3090
|
+
type: "button",
|
|
3091
|
+
onClick: goPrevious,
|
|
3092
|
+
disabled: current <= 1,
|
|
3093
|
+
className: `
|
|
3094
|
+
flex items-center gap-2 p-1 rounded-lg
|
|
3095
|
+
bg-login-700 hover:bg-login-600 disabled:opacity-40
|
|
3096
|
+
border border-login-500/50 text-sm transition-colors duration-150
|
|
3097
|
+
`,
|
|
3098
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5" })
|
|
3099
|
+
}),
|
|
3100
|
+
/* @__PURE__ */ jsx("nav", {
|
|
3101
|
+
className: "flex items-center gap-1",
|
|
3102
|
+
"aria-label": "Pagination",
|
|
3103
|
+
children: pages.map((p, i) => typeof p === "string" ? /* @__PURE__ */ jsx("span", {
|
|
3104
|
+
className: "px-3 py-1 text-sm",
|
|
3105
|
+
children: p
|
|
3106
|
+
}, `e-${i}`) : /* @__PURE__ */ jsx("button", {
|
|
3107
|
+
type: "button",
|
|
3108
|
+
onClick: () => setPage(p),
|
|
3109
|
+
"aria-current": p === current ? "page" : void 0,
|
|
3110
|
+
className: `
|
|
3111
|
+
px-3 py-1 rounded-lg text-sm border transition-colors duration-150
|
|
3112
|
+
${p === current ? "bg-login text-white border-login" : "bg-login-700 border-login-500/50 hover:bg-login-600"}
|
|
3113
|
+
`,
|
|
3114
|
+
children: p
|
|
3115
|
+
}, p))
|
|
3116
|
+
}),
|
|
3117
|
+
/* @__PURE__ */ jsx("button", {
|
|
3118
|
+
type: "button",
|
|
3119
|
+
onClick: goNext,
|
|
3120
|
+
disabled: current >= totalPages,
|
|
3121
|
+
className: `
|
|
3122
|
+
flex items-center gap-2 p-1 rounded-lg select-none
|
|
3123
|
+
bg-login-700 hover:bg-login-600 disabled:opacity-40
|
|
3124
|
+
border border-login-500/50 text-sm transition-colors duration-150
|
|
3125
|
+
`,
|
|
3126
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" })
|
|
3127
|
+
})
|
|
3128
|
+
]
|
|
3129
|
+
})]
|
|
3130
|
+
});
|
|
3131
|
+
}
|
|
3132
|
+
//#endregion
|
|
3133
|
+
//#region src/components/confirm/confirmPopup.tsx
|
|
3134
|
+
function ConfirmPopup({ isOpen, header, description, confirmText = "Confirm", cancelText = "Cancel", onConfirm, onCancel, variant = "default" }) {
|
|
3135
|
+
if (!isOpen) return null;
|
|
3136
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3137
|
+
role: "dialog",
|
|
3138
|
+
"aria-modal": "true",
|
|
3139
|
+
"aria-labelledby": "confirm-popup-header",
|
|
3140
|
+
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
3141
|
+
onClick: onCancel,
|
|
3142
|
+
children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm" }), /* @__PURE__ */ jsxs("div", {
|
|
3143
|
+
className: "\n relative z-10 w-full max-w-md mx-4\n bg-login-800 border border-login-500/50 rounded-xl\n shadow-2xl p-6 flex flex-col gap-4\n ",
|
|
3144
|
+
onClick: (e) => e.stopPropagation(),
|
|
3145
|
+
children: [
|
|
3146
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3147
|
+
className: "flex items-start gap-3",
|
|
3148
|
+
children: [variant !== "default" && /* @__PURE__ */ jsx(TriangleAlert, { className: `w-5 h-5 shrink-0 mt-0.5 ${variant === "danger" ? "stroke-red-400" : "stroke-yellow-400"}` }), /* @__PURE__ */ jsx("h2", {
|
|
3149
|
+
id: "confirm-popup-header",
|
|
3150
|
+
className: "text-login-50 text-base font-semibold leading-snug",
|
|
3151
|
+
children: header
|
|
3152
|
+
})]
|
|
3153
|
+
}),
|
|
3154
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
3155
|
+
className: "text-login-200 text-sm leading-relaxed",
|
|
3156
|
+
children: description
|
|
3157
|
+
}),
|
|
3158
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3159
|
+
className: "flex justify-end gap-2 mt-1",
|
|
3160
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
3161
|
+
type: "button",
|
|
3162
|
+
onClick: onCancel,
|
|
3163
|
+
className: "\n cursor-pointer px-4 py-1.5 rounded-md text-sm font-medium\n bg-login-600 hover:bg-login-500 text-login-100\n transition-colors duration-150 select-none\n ",
|
|
3164
|
+
children: cancelText
|
|
3165
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
3166
|
+
type: "button",
|
|
3167
|
+
onClick: onConfirm,
|
|
3168
|
+
className: `
|
|
3169
|
+
cursor-pointer px-4 py-1.5 rounded-md text-sm font-medium
|
|
3170
|
+
transition-all duration-150 select-none
|
|
3171
|
+
${variant === "danger" ? "bg-red-600 hover:brightness-110 text-white" : variant === "warning" ? "bg-yellow-500 hover:brightness-110 text-black" : "bg-login hover:brightness-110 text-white"}
|
|
3172
|
+
`,
|
|
3173
|
+
children: confirmText
|
|
3174
|
+
})]
|
|
3175
|
+
})
|
|
3176
|
+
]
|
|
3177
|
+
})]
|
|
3178
|
+
});
|
|
3179
|
+
}
|
|
3180
|
+
//#endregion
|
|
3181
|
+
//#region src/components/vulnerability/constants.ts
|
|
3182
|
+
const severityLabel = {
|
|
3183
|
+
critical: "Critical",
|
|
3184
|
+
high: "High",
|
|
3185
|
+
medium: "Medium",
|
|
3186
|
+
low: "Low",
|
|
3187
|
+
unknown: "Unknown"
|
|
3188
|
+
};
|
|
3189
|
+
const severityClasses = {
|
|
3190
|
+
critical: "border-l-red-500",
|
|
3191
|
+
high: "border-l-orange-500",
|
|
3192
|
+
medium: "border-l-amber-500",
|
|
3193
|
+
low: "border-l-green-500",
|
|
3194
|
+
unknown: "border-l-login-400"
|
|
3195
|
+
};
|
|
3196
|
+
//#endregion
|
|
3197
|
+
//#region src/components/vulnerability/severityPill.tsx
|
|
3198
|
+
function SeverityPill({ severity, count, compact = false }) {
|
|
3199
|
+
if (count === 0) return null;
|
|
3200
|
+
return /* @__PURE__ */ jsxs(LeftBarPanel, {
|
|
3201
|
+
color: severityClasses[severity],
|
|
3202
|
+
className: `flex items-center gap-2.5 ${compact ? "px-2.5 py-1.5" : "px-3 py-2"}`,
|
|
3203
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3204
|
+
className: `${compact ? "text-sm" : "text-base"} font-bold text-login-50`,
|
|
3205
|
+
children: count
|
|
3206
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
3207
|
+
className: "text-[10px] font-semibold uppercase tracking-[0.15em] text-login-300",
|
|
3208
|
+
children: severityLabel[severity]
|
|
3209
|
+
})]
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
//#endregion
|
|
3213
|
+
//#region src/components/inputs/toggle.tsx
|
|
3214
|
+
function Toggle({ value, onChange, left, right }) {
|
|
3215
|
+
const active = "bg-login text-white shadow-sm";
|
|
3216
|
+
const idle = "text-login-200 hover:text-login-50 hover:bg-login-500/50";
|
|
3217
|
+
const base = "flex items-center justify-center rounded-md px-3 h-7 transition-all duration-150 gap-1.5 text-sm";
|
|
3218
|
+
function renderContent(opt) {
|
|
3219
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [opt.icon, opt.text && /* @__PURE__ */ jsx("span", { children: opt.text })] });
|
|
3220
|
+
}
|
|
3221
|
+
const isLeftActive = value === left.value;
|
|
3222
|
+
const isRightActive = value === right.value;
|
|
3223
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3224
|
+
className: "flex items-center w-fit bg-login-500/50 border border-login-500 rounded-lg p-1 gap-0.5",
|
|
3225
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
3226
|
+
type: "button",
|
|
3227
|
+
onClick: () => onChange(left.value),
|
|
3228
|
+
"aria-label": left.label ?? left.text,
|
|
3229
|
+
"aria-pressed": isLeftActive,
|
|
3230
|
+
className: `${base} ${isLeftActive ? active : idle}`,
|
|
3231
|
+
children: renderContent(left)
|
|
3232
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
3233
|
+
type: "button",
|
|
3234
|
+
onClick: () => onChange(right.value),
|
|
3235
|
+
"aria-label": right.label ?? right.text,
|
|
3236
|
+
"aria-pressed": isRightActive,
|
|
3237
|
+
className: `${base} ${isRightActive ? active : idle}`,
|
|
3238
|
+
children: renderContent(right)
|
|
3239
|
+
})]
|
|
3240
|
+
});
|
|
3241
|
+
}
|
|
3242
|
+
//#endregion
|
|
3243
|
+
export { Accordion, AccordionGroup, Alert, Button, Checkbox, ConfirmPopup, Footer, GlassCard, Highlight, IconBubble, Input, LanguageToggle, LeftBarPanel, LoginPage, Logo, LogoSmall, MarkdownRender, MenuButton, MultiSelect, NavDropdown, NavItem, Navbar, PageContainer, Pagination, PulseDot, Radio, Range, SearchInput, Select, SeverityPill, StatCard, Switch, TabPanel, Table, Tabs, TagInput, Textarea, ThemeToggle, Toaster, Toggle, VersionTag, loginAddress, loginCopyright, loginEmail, loginSocialLinks, loginSponsor, toast };
|