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.
Files changed (181) hide show
  1. package/README.md +34 -0
  2. package/dist/icons-lZYQ6Vlr.js +125 -0
  3. package/dist/src/components/index.d.ts +706 -30
  4. package/dist/src/components/index.js +3243 -44
  5. package/dist/src/hooks/index.d.ts +15 -3
  6. package/dist/src/hooks/index.js +44 -3
  7. package/dist/src/icons/index.d.ts +420 -0
  8. package/dist/src/icons/index.js +3 -0
  9. package/dist/src/styles/index.d.ts +1 -1
  10. package/dist/src/styles/index.js +2 -1
  11. package/dist/src/utils/index.d.ts +38 -5
  12. package/dist/src/utils/index.js +125 -6
  13. package/dist/{src/globals.css → style.css} +890 -678
  14. package/dist/useClickOutside-Cmp-RsP3.js +13 -0
  15. package/index.d.ts +0 -1
  16. package/package.json +22 -23
  17. package/src/components/alert/alert.tsx +20 -18
  18. package/src/components/buttons/button.tsx +28 -35
  19. package/src/components/confirm/confirmPopup.tsx +15 -17
  20. package/src/components/container/accordion.tsx +54 -0
  21. package/src/components/container/glassCard.tsx +14 -0
  22. package/src/components/container/iconBubble.tsx +30 -0
  23. package/src/components/container/leftBarPanel.tsx +15 -0
  24. package/src/components/container/pulseDot.tsx +31 -0
  25. package/src/components/container/statCard.tsx +24 -0
  26. package/src/components/container/tabs.tsx +64 -0
  27. package/src/components/footer/footer.tsx +124 -0
  28. package/src/components/footer/loginContent.tsx +70 -0
  29. package/src/components/index.ts +15 -0
  30. package/src/components/inputs/checkbox.tsx +4 -4
  31. package/src/components/inputs/input.tsx +11 -13
  32. package/src/components/inputs/multiSelect.tsx +144 -0
  33. package/src/components/inputs/radio.tsx +4 -4
  34. package/src/components/inputs/range.tsx +6 -5
  35. package/src/components/inputs/searchInput.tsx +1 -1
  36. package/src/components/inputs/select.tsx +19 -18
  37. package/src/components/inputs/shared/colorPickerPopup.tsx +5 -5
  38. package/src/components/inputs/shared/dateTimePickerPopup.tsx +9 -9
  39. package/src/components/inputs/shared/inputError.tsx +1 -1
  40. package/src/components/inputs/switch.tsx +7 -7
  41. package/src/components/inputs/tagInput.tsx +6 -7
  42. package/src/components/inputs/textarea.tsx +8 -10
  43. package/src/components/inputs/toggle.tsx +6 -6
  44. package/src/components/table/body.tsx +6 -6
  45. package/src/components/table/format.ts +1 -1
  46. package/src/components/table/header.tsx +1 -1
  47. package/src/components/table/pagination.tsx +17 -31
  48. package/src/components/table/table.tsx +2 -2
  49. package/src/components/version/version.tsx +1 -1
  50. package/src/components/vulnerability/constants.ts +6 -6
  51. package/src/components/vulnerability/severityPill.tsx +6 -7
  52. package/src/hooks/index.ts +1 -0
  53. package/src/hooks/useClickOutside.ts +5 -22
  54. package/src/icons/icons.tsx +431 -0
  55. package/src/icons/index.ts +2 -0
  56. package/src/index.ts +0 -1
  57. package/src/types/hooks.d.ts +8 -2
  58. package/src/utils/index.ts +1 -1
  59. package/src/utils/logoConsoleOutput/logoConsoleOutput.ts +31 -0
  60. package/tsconfig.json +3 -2
  61. package/tsdown.config.ts +26 -0
  62. package/Readme.md +0 -29
  63. package/bun.lock +0 -662
  64. package/dist/src/components/alert/alert.d.ts +0 -8
  65. package/dist/src/components/alert/alert.js +0 -15
  66. package/dist/src/components/buttons/button.d.ts +0 -13
  67. package/dist/src/components/buttons/button.js +0 -30
  68. package/dist/src/components/confirm/confirmPopup.d.ts +0 -12
  69. package/dist/src/components/confirm/confirmPopup.js +0 -18
  70. package/dist/src/components/container/highlight.d.ts +0 -4
  71. package/dist/src/components/container/highlight.js +0 -4
  72. package/dist/src/components/container/page.d.ts +0 -8
  73. package/dist/src/components/container/page.js +0 -4
  74. package/dist/src/components/inputs/checkbox.d.ts +0 -17
  75. package/dist/src/components/inputs/checkbox.js +0 -37
  76. package/dist/src/components/inputs/input.d.ts +0 -12
  77. package/dist/src/components/inputs/input.js +0 -124
  78. package/dist/src/components/inputs/radio.d.ts +0 -17
  79. package/dist/src/components/inputs/radio.js +0 -27
  80. package/dist/src/components/inputs/range.d.ts +0 -11
  81. package/dist/src/components/inputs/range.js +0 -22
  82. package/dist/src/components/inputs/searchInput.d.ts +0 -6
  83. package/dist/src/components/inputs/searchInput.js +0 -42
  84. package/dist/src/components/inputs/select.d.ts +0 -23
  85. package/dist/src/components/inputs/select.js +0 -70
  86. package/dist/src/components/inputs/shared/colorPickerPopup.d.ts +0 -8
  87. package/dist/src/components/inputs/shared/colorPickerPopup.js +0 -191
  88. package/dist/src/components/inputs/shared/dateTimePickerPopup.d.ts +0 -9
  89. package/dist/src/components/inputs/shared/dateTimePickerPopup.js +0 -128
  90. package/dist/src/components/inputs/shared/fieldWrapper.d.ts +0 -14
  91. package/dist/src/components/inputs/shared/fieldWrapper.js +0 -8
  92. package/dist/src/components/inputs/shared/index.d.ts +0 -5
  93. package/dist/src/components/inputs/shared/index.js +0 -5
  94. package/dist/src/components/inputs/shared/inputError.d.ts +0 -6
  95. package/dist/src/components/inputs/shared/inputError.js +0 -6
  96. package/dist/src/components/inputs/shared/inputInfo.d.ts +0 -5
  97. package/dist/src/components/inputs/shared/inputInfo.js +0 -5
  98. package/dist/src/components/inputs/shared/inputLabel.d.ts +0 -9
  99. package/dist/src/components/inputs/shared/inputLabel.js +0 -4
  100. package/dist/src/components/inputs/switch.d.ts +0 -11
  101. package/dist/src/components/inputs/switch.js +0 -14
  102. package/dist/src/components/inputs/tagInput.d.ts +0 -15
  103. package/dist/src/components/inputs/tagInput.js +0 -40
  104. package/dist/src/components/inputs/textarea.d.ts +0 -11
  105. package/dist/src/components/inputs/textarea.js +0 -36
  106. package/dist/src/components/inputs/toggle.d.ts +0 -14
  107. package/dist/src/components/inputs/toggle.js +0 -12
  108. package/dist/src/components/login/loginPage.d.ts +0 -2
  109. package/dist/src/components/login/loginPage.js +0 -18
  110. package/dist/src/components/logo/logo.d.ts +0 -5
  111. package/dist/src/components/logo/logo.js +0 -6
  112. package/dist/src/components/logo/logoSmall.d.ts +0 -1
  113. package/dist/src/components/logo/logoSmall.js +0 -6
  114. package/dist/src/components/markdownrender/markdownRender.d.ts +0 -7
  115. package/dist/src/components/markdownrender/markdownRender.js +0 -26
  116. package/dist/src/components/navbar/bubble.d.ts +0 -14
  117. package/dist/src/components/navbar/bubble.js +0 -8
  118. package/dist/src/components/navbar/navbar.d.ts +0 -34
  119. package/dist/src/components/navbar/navbar.js +0 -36
  120. package/dist/src/components/navbar/navbarDropdown.d.ts +0 -7
  121. package/dist/src/components/navbar/navbarDropdown.js +0 -19
  122. package/dist/src/components/navbar/navbarItem.d.ts +0 -11
  123. package/dist/src/components/navbar/navbarItem.js +0 -12
  124. package/dist/src/components/table/body.d.ts +0 -15
  125. package/dist/src/components/table/body.js +0 -116
  126. package/dist/src/components/table/format.d.ts +0 -1
  127. package/dist/src/components/table/format.js +0 -27
  128. package/dist/src/components/table/header.d.ts +0 -8
  129. package/dist/src/components/table/header.js +0 -47
  130. package/dist/src/components/table/menu.d.ts +0 -17
  131. package/dist/src/components/table/menu.js +0 -30
  132. package/dist/src/components/table/pagination.d.ts +0 -6
  133. package/dist/src/components/table/pagination.js +0 -86
  134. package/dist/src/components/table/table.d.ts +0 -14
  135. package/dist/src/components/table/table.js +0 -14
  136. package/dist/src/components/toast/toastItem.d.ts +0 -2
  137. package/dist/src/components/toast/toastItem.js +0 -38
  138. package/dist/src/components/toast/toaster.d.ts +0 -9
  139. package/dist/src/components/toast/toaster.js +0 -86
  140. package/dist/src/components/toggle/language.d.ts +0 -4
  141. package/dist/src/components/toggle/language.js +0 -29
  142. package/dist/src/components/toggle/theme.d.ts +0 -3
  143. package/dist/src/components/toggle/theme.js +0 -30
  144. package/dist/src/components/version/version.d.ts +0 -7
  145. package/dist/src/components/version/version.js +0 -12
  146. package/dist/src/components/vulnerability/constants.d.ts +0 -4
  147. package/dist/src/components/vulnerability/constants.js +0 -14
  148. package/dist/src/components/vulnerability/severityPill.d.ts +0 -8
  149. package/dist/src/components/vulnerability/severityPill.js +0 -8
  150. package/dist/src/hooks/useClickOutside.d.ts +0 -2
  151. package/dist/src/hooks/useClickOutside.js +0 -27
  152. package/dist/src/hooks/useDarkMode.d.ts +0 -1
  153. package/dist/src/hooks/useDarkMode.js +0 -17
  154. package/dist/src/hooks/useVisibility.d.ts +0 -4
  155. package/dist/src/hooks/useVisibility.js +0 -23
  156. package/dist/src/index.d.ts +0 -5
  157. package/dist/src/index.js +0 -5
  158. package/dist/src/scripts/buildCss.d.ts +0 -1
  159. package/dist/src/scripts/buildCss.js +0 -22
  160. package/dist/src/scripts/index.d.ts +0 -1
  161. package/dist/src/scripts/index.js +0 -1
  162. package/dist/src/scripts/rewriteAlias.d.ts +0 -1
  163. package/dist/src/scripts/rewriteAlias.js +0 -31
  164. package/dist/src/utils/LogoConsoleOutput/LogoConsoleOutput.d.ts +0 -1
  165. package/dist/src/utils/LogoConsoleOutput/LogoConsoleOutput.js +0 -44
  166. package/dist/src/utils/auth/callback.d.ts +0 -2
  167. package/dist/src/utils/auth/callback.js +0 -63
  168. package/dist/src/utils/auth/getDomain.d.ts +0 -2
  169. package/dist/src/utils/auth/getDomain.js +0 -6
  170. package/dist/src/utils/auth/login.d.ts +0 -3
  171. package/dist/src/utils/auth/login.js +0 -14
  172. package/dist/src/utils/auth/logout.d.ts +0 -3
  173. package/dist/src/utils/auth/logout.js +0 -18
  174. package/dist/src/utils/auth/token.d.ts +0 -3
  175. package/dist/src/utils/auth/token.js +0 -33
  176. package/dist/tailwind.config.d.ts +0 -3
  177. package/dist/tailwind.config.js +0 -7
  178. package/src/scripts/buildCss.ts +0 -25
  179. package/src/scripts/index.ts +0 -1
  180. package/src/scripts/rewriteAlias.ts +0 -39
  181. package/src/utils/LogoConsoleOutput/LogoConsoleOutput.ts +0 -61
@@ -1,44 +1,3243 @@
1
- // Input components
2
- export { default as Input } from './inputs/input';
3
- export { default as SearchInput } from './inputs/searchInput';
4
- export { default as Textarea } from './inputs/textarea';
5
- export { default as Checkbox } from './inputs/checkbox';
6
- export { default as Select } from './inputs/select';
7
- export { default as TagInput } from './inputs/tagInput';
8
- export { default as Switch } from './inputs/switch';
9
- export { default as Radio } from './inputs/radio';
10
- export { default as Range } from './inputs/range';
11
- // Logos
12
- export { default as Logo } from './logo/logo';
13
- export { default as LogoSmall } from './logo/logoSmall';
14
- // Toggles
15
- export { default as ThemeToggle } from './toggle/theme';
16
- export { default as LanguageToggle } from './toggle/language';
17
- // Navbar
18
- export { default as Navbar } from './navbar/navbar';
19
- export { default as NavItem } from './navbar/navbarItem';
20
- export { default as NavDropdown } from './navbar/navbarDropdown';
21
- // Containers
22
- export { default as PageContainer } from './container/page';
23
- export { default as Highlight } from './container/highlight';
24
- // Login
25
- export { default as VersionTag } from './version/version';
26
- export { default as LoginPage } from './login/loginPage';
27
- // Toasts
28
- export { default as Toaster, toast } from './toast/toaster';
29
- // Buttons
30
- export { default as Button } from './buttons/button';
31
- // Alert
32
- export { default as Alert } from './alert/alert';
33
- // Table
34
- export { MenuButton } from './table/menu';
35
- export { default as Table } from './table/table';
36
- export { default as Pagination } from './table/pagination';
37
- // Markdown
38
- export { default as MarkdownRender } from './markdownrender/markdownRender';
39
- // Confirm
40
- export { default as ConfirmPopup } from './confirm/confirmPopup';
41
- // Vulnerability
42
- export { default as SeverityPill } from './vulnerability/severityPill';
43
- // Layout
44
- export { default as Toggle } from './inputs/toggle';
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 };