uibee 3.2.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/dist/components/alert/alert.d.ts +15 -0
  2. package/dist/components/alert/alert.js +29 -0
  3. package/dist/components/badge/badge.d.ts +16 -0
  4. package/dist/components/badge/badge.js +26 -0
  5. package/dist/components/buttons/button.d.ts +25 -0
  6. package/dist/components/buttons/button.js +44 -0
  7. package/dist/components/code/code.d.ts +23 -0
  8. package/dist/components/code/code.js +39 -0
  9. package/dist/components/confirm/confirmPopup.d.ts +23 -0
  10. package/dist/components/confirm/confirmPopup.js +52 -0
  11. package/dist/components/container/accordion.d.ts +25 -0
  12. package/dist/components/container/accordion.js +41 -0
  13. package/dist/components/container/card.d.ts +13 -0
  14. package/dist/components/container/card.js +10 -0
  15. package/dist/components/container/expandableCard.d.ts +32 -0
  16. package/dist/components/container/expandableCard.js +70 -0
  17. package/dist/components/container/glassCard.d.ts +13 -0
  18. package/dist/components/container/glassCard.js +10 -0
  19. package/dist/components/container/highlight.d.ts +10 -0
  20. package/dist/components/container/highlight.js +10 -0
  21. package/dist/components/container/iconBubble.d.ts +25 -0
  22. package/dist/components/container/iconBubble.js +21 -0
  23. package/dist/components/container/leftBarPanel.d.ts +15 -0
  24. package/dist/components/container/leftBarPanel.js +10 -0
  25. package/dist/components/container/page.d.ts +15 -0
  26. package/dist/components/container/page.js +16 -0
  27. package/dist/components/container/pulseDot.d.ts +12 -0
  28. package/dist/components/container/pulseDot.js +23 -0
  29. package/dist/components/container/statCard.d.ts +18 -0
  30. package/dist/components/container/statCard.js +25 -0
  31. package/dist/components/container/tabs.d.ts +35 -0
  32. package/dist/components/container/tabs.js +36 -0
  33. package/dist/components/empty/emptyState.d.ts +19 -0
  34. package/dist/components/empty/emptyState.js +27 -0
  35. package/dist/components/footer/footer.d.ts +49 -0
  36. package/dist/components/footer/footer.js +109 -0
  37. package/dist/components/footer/loginContent.d.ts +18 -0
  38. package/dist/components/footer/loginContent.js +138 -0
  39. package/dist/components/inputs/checkbox.d.ts +20 -0
  40. package/dist/components/inputs/checkbox.js +76 -0
  41. package/dist/components/inputs/fileInput.d.ts +19 -0
  42. package/dist/components/inputs/fileInput.js +108 -0
  43. package/dist/components/inputs/input.d.ts +16 -0
  44. package/dist/components/inputs/input.js +157 -0
  45. package/dist/components/inputs/multiSelect.d.ts +37 -0
  46. package/dist/components/inputs/multiSelect.js +99 -0
  47. package/dist/components/inputs/radio.d.ts +20 -0
  48. package/dist/components/inputs/radio.js +70 -0
  49. package/dist/components/inputs/range.d.ts +14 -0
  50. package/dist/components/inputs/range.js +60 -0
  51. package/dist/components/inputs/searchInput.d.ts +11 -0
  52. package/dist/components/inputs/searchInput.js +56 -0
  53. package/dist/components/inputs/select.d.ts +42 -0
  54. package/dist/components/inputs/select.js +164 -0
  55. package/dist/components/inputs/shared/colorPickerPopup.js +293 -0
  56. package/dist/components/inputs/shared/dateTimePickerPopup.js +225 -0
  57. package/dist/components/inputs/shared/fieldWrapper.js +33 -0
  58. package/dist/components/inputs/shared/index.js +6 -0
  59. package/dist/components/inputs/shared/inputError.js +17 -0
  60. package/dist/components/inputs/shared/inputInfo.js +13 -0
  61. package/dist/components/inputs/shared/inputLabel.js +19 -0
  62. package/dist/components/inputs/switch.d.ts +14 -0
  63. package/dist/components/inputs/switch.js +37 -0
  64. package/dist/components/inputs/tagInput.d.ts +31 -0
  65. package/dist/components/inputs/tagInput.js +72 -0
  66. package/dist/components/inputs/textarea.d.ts +14 -0
  67. package/dist/components/inputs/textarea.js +76 -0
  68. package/dist/components/inputs/toggle.d.ts +21 -0
  69. package/dist/components/inputs/toggle.js +33 -0
  70. package/dist/components/login/loginPage.d.ts +15 -0
  71. package/dist/components/login/loginPage.js +80 -0
  72. package/dist/components/logo/logo.d.ts +9 -0
  73. package/dist/components/logo/logo.js +138 -0
  74. package/dist/components/logo/logoSmall.d.ts +4 -0
  75. package/dist/components/logo/logoSmall.js +56 -0
  76. package/dist/components/markdownrender/markdownRender.d.ts +16 -0
  77. package/dist/components/markdownrender/markdownRender.js +59 -0
  78. package/dist/components/modal/modal.d.ts +22 -0
  79. package/dist/components/modal/modal.js +59 -0
  80. package/dist/components/navbar/bubble.js +36 -0
  81. package/dist/components/navbar/navbar.d.ts +50 -0
  82. package/dist/components/navbar/navbar.js +99 -0
  83. package/dist/components/navbar/navbarDropdown.d.ts +15 -0
  84. package/dist/components/navbar/navbarDropdown.js +63 -0
  85. package/dist/components/navbar/navbarItem.d.ts +23 -0
  86. package/dist/components/navbar/navbarItem.js +38 -0
  87. package/dist/components/sidebar/sidebar.d.ts +34 -0
  88. package/dist/components/sidebar/sidebar.js +135 -0
  89. package/dist/components/spinner/spinner.d.ts +11 -0
  90. package/dist/components/spinner/spinner.js +16 -0
  91. package/dist/components/table/body.js +253 -0
  92. package/dist/components/table/constants.js +58 -0
  93. package/dist/components/table/empty.js +24 -0
  94. package/dist/components/table/format.js +39 -0
  95. package/dist/components/table/header.js +109 -0
  96. package/dist/components/table/menu.d.ts +18 -0
  97. package/dist/components/table/menu.js +76 -0
  98. package/dist/components/table/pagination.d.ts +14 -0
  99. package/dist/components/table/pagination.js +130 -0
  100. package/dist/components/table/skeleton.js +39 -0
  101. package/dist/components/table/table.d.ts +7 -0
  102. package/dist/components/table/table.js +213 -0
  103. package/dist/components/table/types.d.ts +52 -0
  104. package/dist/components/table/utils.js +9 -0
  105. package/dist/components/toast/toastItem.js +61 -0
  106. package/dist/components/toast/toaster.d.ts +13 -0
  107. package/dist/components/toast/toaster.js +117 -0
  108. package/dist/components/toggle/language.d.ts +10 -0
  109. package/dist/components/toggle/language.js +34 -0
  110. package/dist/components/toggle/theme.d.ts +8 -0
  111. package/dist/components/toggle/theme.js +135 -0
  112. package/dist/components/version/version.d.ts +13 -0
  113. package/dist/components/version/version.js +19 -0
  114. package/dist/components/vulnerability/constants.d.ts +4 -0
  115. package/dist/components/vulnerability/constants.js +17 -0
  116. package/dist/components/vulnerability/severityPill.d.ts +15 -0
  117. package/dist/components/vulnerability/severityPill.js +20 -0
  118. package/dist/{style.css → globals.css} +155 -226
  119. package/dist/hooks/useClickOutside.d.ts +6 -0
  120. package/dist/{useClickOutside-Cmp-RsP3.js → hooks/useClickOutside.js} +1 -1
  121. package/dist/hooks/useDarkMode.d.ts +4 -0
  122. package/dist/hooks/useDarkMode.js +19 -0
  123. package/dist/hooks/useVisibility.d.ts +7 -0
  124. package/dist/hooks/useVisibility.js +25 -0
  125. package/dist/icons/icons.d.ts +420 -0
  126. package/dist/{icons-lZYQ6Vlr.js → icons/icons.js} +1 -1
  127. package/dist/src/components/index.d.ts +51 -901
  128. package/dist/src/components/index.js +49 -4160
  129. package/dist/src/hooks/index.d.ts +3 -14
  130. package/dist/src/hooks/index.js +3 -42
  131. package/dist/src/icons/index.d.ts +1 -419
  132. package/dist/src/icons/index.js +1 -1
  133. package/dist/src/styles/index.js +1 -1
  134. package/dist/src/utils/index.d.ts +5 -37
  135. package/dist/src/utils/index.js +5 -124
  136. package/dist/utils/auth/callback.d.ts +14 -0
  137. package/dist/utils/auth/callback.js +53 -0
  138. package/dist/utils/auth/getDomain.js +6 -0
  139. package/dist/utils/auth/login.d.ts +12 -0
  140. package/dist/utils/auth/login.js +17 -0
  141. package/dist/utils/auth/logout.d.ts +10 -0
  142. package/dist/utils/auth/logout.js +20 -0
  143. package/dist/utils/auth/token.d.ts +10 -0
  144. package/dist/utils/auth/token.js +30 -0
  145. package/dist/utils/logoConsoleOutput/logoConsoleOutput.d.ts +4 -0
  146. package/dist/utils/logoConsoleOutput/logoConsoleOutput.js +11 -0
  147. package/package.json +1 -1
  148. package/src/components/buttons/button.tsx +2 -0
  149. package/src/components/footer/footer.tsx +65 -28
  150. package/src/components/index.ts +0 -1
  151. package/src/components/inputs/checkbox.tsx +2 -0
  152. package/src/components/inputs/input.tsx +2 -0
  153. package/src/components/inputs/radio.tsx +2 -0
  154. package/src/components/inputs/range.tsx +2 -0
  155. package/src/components/inputs/shared/colorPickerPopup.tsx +2 -0
  156. package/src/components/inputs/shared/dateTimePickerPopup.tsx +2 -0
  157. package/src/components/inputs/textarea.tsx +2 -0
  158. package/src/components/inputs/toggle.tsx +2 -0
  159. package/src/components/sidebar/sidebar.tsx +37 -10
  160. package/src/components/toast/toastItem.tsx +2 -0
  161. package/src/globals.css +6 -1
  162. package/tsdown.config.ts +1 -0
@@ -0,0 +1,63 @@
1
+ "use client";
2
+ import React, { useRef, useState } from "react";
3
+ import { ChevronDown } from "lucide-react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/components/navbar/navbarDropdown.tsx
6
+ function NavDropdown({ children, title, className }) {
7
+ const [isMobileDropdownOpen, setIsMobileDropdownOpen] = useState(false);
8
+ const [isDesktopOpen, setIsDesktopOpen] = useState(false);
9
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
10
+ className: "relative hidden 800px:block",
11
+ children: /* @__PURE__ */ jsxs("div", {
12
+ className: "outline-none",
13
+ tabIndex: 0,
14
+ ref: useRef(null),
15
+ onMouseEnter: () => setIsDesktopOpen(true),
16
+ onMouseLeave: () => setIsDesktopOpen(false),
17
+ onFocus: () => setIsDesktopOpen(true),
18
+ onBlur: () => setIsDesktopOpen(false),
19
+ children: [/* @__PURE__ */ jsxs("div", {
20
+ className: `list-none no-underline text-base leading-4 p-3 font-bold cursor-pointer flex flex-row items-center
21
+ transition-colors`,
22
+ children: [title, /* @__PURE__ */ jsx(ChevronDown, { className: "w-6 h-6 stroke-login ml-1 text-2xl transition-transform duration-300 ease-in-out" })]
23
+ }), /* @__PURE__ */ jsx("div", {
24
+ 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"}`,
25
+ children: /* @__PURE__ */ jsx("ul", {
26
+ 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 || ""}`,
27
+ onClick: () => setIsDesktopOpen(false),
28
+ children: React.Children.map(children, (child, index) => /* @__PURE__ */ jsx("div", {
29
+ onClick: () => setIsDesktopOpen(false),
30
+ className: "group dropdown",
31
+ children: child
32
+ }, index))
33
+ })
34
+ })]
35
+ })
36
+ }), /* @__PURE__ */ jsxs("div", {
37
+ className: "block 800px:hidden!",
38
+ children: [/* @__PURE__ */ jsx("button", {
39
+ className: "bg-none border-none cursor-pointer w-full text-left",
40
+ onClick: (e) => {
41
+ e.stopPropagation();
42
+ setIsMobileDropdownOpen(!isMobileDropdownOpen);
43
+ },
44
+ children: /* @__PURE__ */ jsxs("li", {
45
+ className: `list-none no-underline text-2xl leading-6 overflow-hidden
46
+ w-full pl-4 pr-4 rounded-[0.3rem] transition-all duration-600
47
+ flex items-center gap-2 opacity-100 min-h-16 py-5 `,
48
+ children: [/* @__PURE__ */ jsx("span", { children: title }), /* @__PURE__ */ jsx(ChevronDown, { className: `w-6 h-6 transition-transform duration-400 shrink-0
49
+ ${isMobileDropdownOpen ? "rotate-180" : ""}` })]
50
+ })
51
+ }), /* @__PURE__ */ jsx("div", {
52
+ className: `list-none no-underline text-xl px-6 ${isMobileDropdownOpen ? "pb-4" : ""}`,
53
+ children: React.Children.map(children, (child, index) => /* @__PURE__ */ jsx("div", {
54
+ className: `leading-6 transition-all duration-500 group dropdown
55
+ ${isMobileDropdownOpen ? "h-11 opacity-100" : "h-0 opacity-0"}
56
+ `,
57
+ children: child
58
+ }, index))
59
+ })]
60
+ })] });
61
+ }
62
+ //#endregion
63
+ export { NavDropdown as default };
@@ -0,0 +1,23 @@
1
+ import { ReactNode } from "react";
2
+
3
+ //#region src/components/navbar/navbarItem.d.ts
4
+ type NavItemProps = {
5
+ href: string;
6
+ children: ReactNode;
7
+ external?: boolean;
8
+ target?: string;
9
+ rel?: string;
10
+ title?: string;
11
+ icon?: ReactNode;
12
+ };
13
+ declare function NavItem({
14
+ href,
15
+ children,
16
+ external,
17
+ target,
18
+ rel,
19
+ title,
20
+ icon
21
+ }: NavItemProps): import("react").JSX.Element;
22
+ //#endregion
23
+ export { NavItemProps, NavItem as default };
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import { ArrowUpRight } from "lucide-react";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ import Link from "next/link.js";
5
+ //#region src/components/navbar/navbarItem.tsx
6
+ const commonStyling = "list-none flex no-underline items-center gap-2 whitespace-nowrap cursor-pointer";
7
+ function NavItem({ href, children, external = false, target, rel, title, icon }) {
8
+ const linkProps = {
9
+ href,
10
+ target,
11
+ rel,
12
+ title
13
+ };
14
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Link, {
15
+ ...linkProps,
16
+ className: "hidden 800px:flex",
17
+ children: /* @__PURE__ */ jsxs("li", {
18
+ className: `${commonStyling} text-base leading-4 p-3 font-bold transition-colors link-corner-hover
19
+ group-[.dropdown]:p-2.5 group-[.dropdown]:pr-3 group-[.dropdown]:pl-1`,
20
+ children: [
21
+ icon,
22
+ children,
23
+ external && /* @__PURE__ */ jsx(ArrowUpRight, { className: "w-6 h-6 stroke-login" })
24
+ ]
25
+ })
26
+ }), /* @__PURE__ */ jsx(Link, {
27
+ ...linkProps,
28
+ className: "800px:hidden",
29
+ children: /* @__PURE__ */ jsxs("li", {
30
+ className: `${commonStyling} text-2xl leading-6 overflow-hidden w-auto pl-4 rounded-[0.3rem] transition-all
31
+ duration-600 opacity-100 h-16 py-5 group-[.dropdown]:p-0 group-[.dropdown]:text-lg group-[.dropdown]:h-auto
32
+ group-[.dropdown]:py-2.5 group-[.dropdown]:pl-4`,
33
+ children: [children, external && /* @__PURE__ */ jsx(ArrowUpRight, { className: "w-6 h-6 stroke-login" })]
34
+ })
35
+ })] });
36
+ }
37
+ //#endregion
38
+ export { NavItem as default };
@@ -0,0 +1,34 @@
1
+ import { ElementType, ReactNode } from "react";
2
+
3
+ //#region src/components/sidebar/sidebar.d.ts
4
+ type SidebarSubItem = {
5
+ name: string;
6
+ path: string;
7
+ };
8
+ type SidebarItem = {
9
+ name: string;
10
+ path: string;
11
+ icon: ElementType;
12
+ status?: ReactNode;
13
+ items?: SidebarSubItem[];
14
+ };
15
+ type SidebarProps = {
16
+ items: SidebarItem[];
17
+ header?: ReactNode | ((expanded: boolean) => ReactNode);
18
+ bottomAction?: (expanded: boolean) => ReactNode;
19
+ mobile?: boolean;
20
+ initialExpanded?: boolean;
21
+ onExpandedChange?: (expanded: boolean) => void;
22
+ className?: string;
23
+ };
24
+ declare function Sidebar({
25
+ items,
26
+ header,
27
+ bottomAction,
28
+ mobile,
29
+ initialExpanded,
30
+ onExpandedChange,
31
+ className
32
+ }: SidebarProps): import("react").JSX.Element;
33
+ //#endregion
34
+ export { SidebarItem, SidebarSubItem, Sidebar as default };
@@ -0,0 +1,135 @@
1
+ "use client";
2
+ import { useState } from "react";
3
+ import { ChevronLeft, ChevronRight } from "lucide-react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { usePathname, useSearchParams } from "next/navigation.js";
6
+ import Link from "next/link.js";
7
+ //#region src/components/sidebar/sidebar.tsx
8
+ const ITEM_HEIGHT = 48;
9
+ const GAP = 4;
10
+ const SUB_STRIDE = 40;
11
+ function Sidebar({ items, header, bottomAction, mobile = false, initialExpanded = true, onExpandedChange, className = "" }) {
12
+ const [expanded, setExpanded] = useState(initialExpanded);
13
+ const pathname = usePathname();
14
+ const searchParams = useSearchParams();
15
+ const fullPath = pathname + (searchParams.toString() ? `?${searchParams.toString()}` : "");
16
+ function toggleExpanded() {
17
+ const next = !expanded;
18
+ setExpanded(next);
19
+ onExpandedChange?.(next);
20
+ }
21
+ function isSubActive(sub) {
22
+ return sub.path.includes("?") ? fullPath.startsWith(sub.path) : pathname === sub.path;
23
+ }
24
+ function isItemActive(item) {
25
+ return pathname === item.path || !!item.items?.some((sub) => sub.path.includes("?") ? fullPath.startsWith(sub.path) : pathname === sub.path || pathname.startsWith(sub.path + "/"));
26
+ }
27
+ const activeIndex = items.findIndex(isItemActive);
28
+ const activeOffset = items.slice(0, Math.max(activeIndex, 0)).reduce((acc, item) => acc + ITEM_HEIGHT + (item.items ? GAP : 0) + GAP, 0);
29
+ return /* @__PURE__ */ jsxs("aside", {
30
+ className: `
31
+ flex flex-col border-r border-login-100/10 bg-login-900
32
+ transition-all duration-300 ease-in-out
33
+ ${mobile ? "w-full" : `h-full ${expanded ? "w-64" : "w-20"}`}
34
+ ${className}
35
+ `,
36
+ children: [
37
+ !mobile && /* @__PURE__ */ jsxs("div", {
38
+ className: `relative mb-2 p-4 transition-all duration-300 ${expanded ? "h-16" : "h-20"}`,
39
+ children: [header && /* @__PURE__ */ jsx("div", {
40
+ className: `
41
+ absolute top-4 flex items-center transition-all duration-300
42
+ ${expanded ? "left-4 gap-3" : "left-1/2 -translate-x-1/2 gap-0"}
43
+ `,
44
+ children: typeof header === "function" ? header(expanded) : header
45
+ }), /* @__PURE__ */ jsx("button", {
46
+ onClick: toggleExpanded,
47
+ className: `
48
+ absolute cursor-pointer rounded-lg p-1.5
49
+ text-login-200 transition-all duration-300 hover:bg-login-800
50
+ ${expanded ? "right-4 top-4" : "left-1/2 top-12 -translate-x-1/2"}
51
+ `,
52
+ children: expanded ? /* @__PURE__ */ jsx(ChevronLeft, { size: 20 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 20 })
53
+ })]
54
+ }),
55
+ mobile && /* @__PURE__ */ jsx("div", { className: "h-4" }),
56
+ /* @__PURE__ */ jsxs("div", {
57
+ className: "relative flex flex-1 flex-col gap-1 overflow-x-hidden overflow-y-auto px-3 [scrollbar-width:none]",
58
+ children: [activeIndex >= 0 && /* @__PURE__ */ jsx("span", {
59
+ "aria-hidden": true,
60
+ className: "absolute left-3 right-3 top-0 h-12 rounded-lg bg-login-800 transition-transform duration-300 ease-in-out",
61
+ style: { transform: `translateY(${activeOffset}px)` }
62
+ }), items.map((item, index) => {
63
+ const isActive = isItemActive(item);
64
+ const Icon = item.icon;
65
+ const activeSubIndex = item.items ? item.items.findIndex(isSubActive) : -1;
66
+ return /* @__PURE__ */ jsxs("div", {
67
+ className: "flex flex-col gap-1",
68
+ children: [/* @__PURE__ */ jsxs(Link, {
69
+ href: item.path,
70
+ title: !expanded ? item.name : void 0,
71
+ className: `
72
+ group relative z-10 flex items-center
73
+ overflow-hidden rounded-lg p-3 transition-all duration-200
74
+ ${isActive ? "text-login" : "text-login-200 hover:bg-login-800/50 hover:text-login-100"}
75
+ `,
76
+ children: [
77
+ /* @__PURE__ */ jsx("div", {
78
+ className: `
79
+ flex min-w-6 w-6 items-center justify-center transition-all duration-300
80
+ ${expanded ? "" : "translate-x-1"}
81
+ ${isActive ? "[&>svg]:stroke-login" : "group-hover:[&>svg]:stroke-login-100"}
82
+ `,
83
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" })
84
+ }),
85
+ /* @__PURE__ */ jsx("span", {
86
+ className: `
87
+ whitespace-nowrap overflow-hidden transition-all duration-300
88
+ ${expanded ? "ml-3 max-w-48 opacity-100" : "ml-0 max-w-0 opacity-0"}
89
+ `,
90
+ children: item.name
91
+ }),
92
+ item.status && /* @__PURE__ */ jsx("div", {
93
+ className: `
94
+ flex items-center justify-center
95
+ ${expanded ? "ml-auto" : "absolute right-1 top-1 scale-75"}
96
+ `,
97
+ children: item.status
98
+ })
99
+ ]
100
+ }), item.items && /* @__PURE__ */ jsxs("div", {
101
+ className: `
102
+ relative ml-6 flex flex-col gap-1 overflow-hidden
103
+ border-l border-login-800 pl-2
104
+ transition-all duration-300 ease-in-out
105
+ ${expanded && isActive ? "max-h-96 opacity-100" : "max-h-0 opacity-0"}
106
+ `,
107
+ children: [activeSubIndex >= 0 && /* @__PURE__ */ jsx("span", {
108
+ "aria-hidden": true,
109
+ className: "\n absolute left-2 right-0 top-0 h-9 rounded-lg\n bg-login-800/50 transition-transform duration-300 ease-in-out\n ",
110
+ style: { transform: `translateY(${activeSubIndex * SUB_STRIDE}px)` }
111
+ }), item.items.map((sub, subIndex) => {
112
+ const subActive = isSubActive(sub);
113
+ return /* @__PURE__ */ jsx(Link, {
114
+ href: sub.path,
115
+ className: `
116
+ relative z-10 rounded-lg p-2 text-sm
117
+ transition-all duration-200
118
+ ${subActive ? "text-login" : "text-login-300 hover:bg-login-800/30 hover:text-login-100"}
119
+ `,
120
+ children: sub.name
121
+ }, `${index}-${subIndex}`);
122
+ })]
123
+ })]
124
+ }, index);
125
+ })]
126
+ }),
127
+ bottomAction && /* @__PURE__ */ jsx("div", {
128
+ className: "border-t border-login-100/10 p-3",
129
+ children: bottomAction(expanded)
130
+ })
131
+ ]
132
+ });
133
+ }
134
+ //#endregion
135
+ export { Sidebar as default };
@@ -0,0 +1,11 @@
1
+ //#region src/components/spinner/spinner.d.ts
2
+ type SpinnerProps = {
3
+ size?: 'sm' | 'md' | 'lg';
4
+ className?: string;
5
+ };
6
+ declare function Spinner({
7
+ size,
8
+ className
9
+ }: SpinnerProps): import("react").JSX.Element;
10
+ //#endregion
11
+ export { Spinner as default };
@@ -0,0 +1,16 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ //#region src/components/spinner/spinner.tsx
3
+ const sizes = {
4
+ sm: "w-4 h-4 border-2",
5
+ md: "w-6 h-6 border-2",
6
+ lg: "w-9 h-9 border-[3px]"
7
+ };
8
+ function Spinner({ size = "md", className = "" }) {
9
+ return /* @__PURE__ */ jsx("div", {
10
+ role: "status",
11
+ "aria-label": "Loading",
12
+ className: `rounded-full border-login-500 border-t-login animate-spin ${sizes[size]} ${className}`
13
+ });
14
+ }
15
+ //#endregion
16
+ export { Spinner as default };
@@ -0,0 +1,253 @@
1
+ "use client";
2
+ import { DENSITY_TD, HIGHLIGHT, VARIANT_ROW_BORDER, VARIANT_ROW_HOVER, VARIANT_ROW_STRIPED, VARIANT_TBODY } from "./constants.js";
3
+ import { formatValue } from "./format.js";
4
+ import { resolveId } from "./utils.js";
5
+ import Menu from "./menu.js";
6
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
7
+ import { ChevronDown, EllipsisVertical } from "lucide-react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { useRouter } from "next/navigation.js";
10
+ //#region src/components/table/body.tsx
11
+ function useClickOutside(ref, cb, enabled) {
12
+ useEffect(() => {
13
+ if (!enabled) return;
14
+ function handler(e) {
15
+ if (ref.current && !ref.current.contains(e.target)) cb();
16
+ }
17
+ document.addEventListener("mousedown", handler);
18
+ return () => document.removeEventListener("mousedown", handler);
19
+ }, [
20
+ ref,
21
+ cb,
22
+ enabled
23
+ ]);
24
+ }
25
+ function resolveRedirectUrl(redirectPath, row, id) {
26
+ if (!redirectPath) return null;
27
+ const cfg = typeof redirectPath === "string" ? {
28
+ path: redirectPath,
29
+ key: void 0
30
+ } : redirectPath;
31
+ if (!cfg.path) return null;
32
+ const rid = cfg.key ? String(row[cfg.key] ?? id) : id;
33
+ return cfg.path.includes("?") ? `${cfg.path}${rid}` : `${cfg.path}/${rid}`;
34
+ }
35
+ function Cell({ col, row, density, variant }) {
36
+ const value = row[col.key];
37
+ const shouldTruncate = col.truncate === true;
38
+ const align = col.align ?? "left";
39
+ const wrapperAlign = align === "right" ? "text-right" : align === "center" ? "text-center" : "";
40
+ let content;
41
+ if (col.render) content = col.render(value, row);
42
+ else if (col.highlight) {
43
+ const colorName = col.highlight[String(value)] ?? col.highlight["default"];
44
+ const formatted = String(formatValue(col.key, value));
45
+ if (colorName) content = /* @__PURE__ */ jsx("span", {
46
+ className: `inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${HIGHLIGHT[colorName]}`,
47
+ children: formatted
48
+ });
49
+ else content = /* @__PURE__ */ jsx("span", {
50
+ className: shouldTruncate ? "block truncate" : "whitespace-nowrap",
51
+ children: formatted
52
+ });
53
+ } else {
54
+ const formatted = formatValue(col.key, value);
55
+ content = /* @__PURE__ */ jsx("span", {
56
+ className: shouldTruncate ? "block truncate" : "whitespace-nowrap",
57
+ children: formatted === null || formatted === void 0 ? "-" : String(formatted)
58
+ });
59
+ }
60
+ return /* @__PURE__ */ jsx("td", {
61
+ style: col.width ? {
62
+ width: col.width,
63
+ maxWidth: col.width
64
+ } : void 0,
65
+ className: `
66
+ align-middle text-sm text-login-75 ${wrapperAlign}
67
+ ${DENSITY_TD[density]} ${VARIANT_ROW_BORDER[variant]}
68
+ `,
69
+ children: content
70
+ });
71
+ }
72
+ function Body({ data, columns, idKey, variant, density, striped, redirectPath, onRowClick, renderExpandedRow, selectable, selectedIds, onSelectionChange, menuItems }) {
73
+ const router = useRouter();
74
+ const [openMenuId, setOpenMenuId] = useState(null);
75
+ const [anchor, setAnchor] = useState(null);
76
+ const [expandedId, setExpandedId] = useState(null);
77
+ const menuRef = useRef(null);
78
+ const menuWasOpenOnMouseDown = useRef(false);
79
+ const closeMenu = useCallback(() => setOpenMenuId(null), []);
80
+ useClickOutside(menuRef, closeMenu, openMenuId !== null);
81
+ useEffect(() => {
82
+ if (openMenuId === null) return;
83
+ document.addEventListener("scroll", closeMenu, true);
84
+ return () => document.removeEventListener("scroll", closeMenu, true);
85
+ }, [closeMenu, openMenuId]);
86
+ function openMenu(id, coords) {
87
+ setAnchor(coords);
88
+ setOpenMenuId(id);
89
+ }
90
+ const selectedSet = useMemo(() => new Set(selectedIds), [selectedIds]);
91
+ function toggleSelect(id) {
92
+ onSelectionChange(selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]);
93
+ }
94
+ const hasMenu = Boolean(menuItems);
95
+ const hasExpand = Boolean(renderExpandedRow);
96
+ return /* @__PURE__ */ jsx("tbody", {
97
+ className: VARIANT_TBODY[variant],
98
+ children: data.map((row, rowIdx) => {
99
+ const id = resolveId(row, idKey, columns);
100
+ const url = resolveRedirectUrl(redirectPath, row, id);
101
+ const isClickable = Boolean(url || onRowClick || hasExpand);
102
+ const isMenuOpen = openMenuId === id;
103
+ const isExpanded = expandedId === id;
104
+ const isSelected = selectable && selectedSet.has(id);
105
+ const expandedContent = renderExpandedRow?.(row);
106
+ const rowClass = [
107
+ "transition-colors duration-100",
108
+ isClickable ? "cursor-pointer" : "",
109
+ VARIANT_ROW_HOVER[variant],
110
+ striped ? VARIANT_ROW_STRIPED[variant] : "",
111
+ isSelected ? "bg-login/5" : ""
112
+ ].filter(Boolean).join(" ");
113
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [/* @__PURE__ */ jsxs("tr", {
114
+ className: rowClass,
115
+ onMouseEnter: () => {
116
+ if (url) router.prefetch(url);
117
+ },
118
+ onMouseDown: () => {
119
+ menuWasOpenOnMouseDown.current = openMenuId !== null;
120
+ },
121
+ onClick: () => {
122
+ if (menuWasOpenOnMouseDown.current) {
123
+ menuWasOpenOnMouseDown.current = false;
124
+ return;
125
+ }
126
+ if (hasExpand) {
127
+ setExpandedId(isExpanded ? null : id);
128
+ return;
129
+ }
130
+ if (onRowClick) {
131
+ onRowClick(row, id);
132
+ return;
133
+ }
134
+ if (url) router.push(url);
135
+ },
136
+ onContextMenu: (e) => {
137
+ if (!hasMenu) return;
138
+ e.preventDefault();
139
+ openMenu(id, {
140
+ top: e.clientY,
141
+ right: window.innerWidth - e.clientX
142
+ });
143
+ },
144
+ children: [
145
+ selectable && /* @__PURE__ */ jsx("td", {
146
+ className: `align-middle ${VARIANT_ROW_BORDER[variant]}`,
147
+ style: {
148
+ width: "3rem",
149
+ minWidth: "3rem"
150
+ },
151
+ children: /* @__PURE__ */ jsx("div", {
152
+ className: "flex items-center justify-center",
153
+ children: /* @__PURE__ */ jsx("button", {
154
+ type: "button",
155
+ "aria-label": isSelected ? "Deselect row" : "Select row",
156
+ "aria-checked": isSelected,
157
+ role: "checkbox",
158
+ onClick: (e) => {
159
+ e.stopPropagation();
160
+ toggleSelect(id);
161
+ },
162
+ className: `
163
+ h-4 w-4 rounded border flex items-center justify-center transition-colors cursor-pointer
164
+ ${isSelected ? "bg-login border-login text-white" : "border-login-400 bg-transparent hover:border-login-100"}
165
+ `,
166
+ children: isSelected && /* @__PURE__ */ jsx("svg", {
167
+ className: "h-3 w-3",
168
+ viewBox: "0 0 12 12",
169
+ fill: "none",
170
+ children: /* @__PURE__ */ jsx("path", {
171
+ d: "M2 6l3 3 5-5",
172
+ stroke: "currentColor",
173
+ strokeWidth: "1.5",
174
+ strokeLinecap: "round",
175
+ strokeLinejoin: "round"
176
+ })
177
+ })
178
+ })
179
+ })
180
+ }),
181
+ columns.map((col) => /* @__PURE__ */ jsx(Cell, {
182
+ col,
183
+ row,
184
+ density,
185
+ variant
186
+ }, col.key)),
187
+ hasExpand && /* @__PURE__ */ jsx("td", {
188
+ className: `align-middle ${VARIANT_ROW_BORDER[variant]}`,
189
+ style: {
190
+ width: "2.5rem",
191
+ minWidth: "2.5rem"
192
+ },
193
+ children: /* @__PURE__ */ jsx("div", {
194
+ className: "flex items-center justify-center",
195
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: `
196
+ h-4 w-4 transition-transform duration-200
197
+ ${isExpanded ? "rotate-180 text-login" : "text-login-400"}
198
+ ` })
199
+ })
200
+ }),
201
+ hasMenu && /* @__PURE__ */ jsx("td", {
202
+ className: `align-middle pr-3 ${VARIANT_ROW_BORDER[variant]}`,
203
+ style: {
204
+ width: "3.5rem",
205
+ minWidth: "3.5rem"
206
+ },
207
+ children: /* @__PURE__ */ jsxs("div", {
208
+ className: "relative flex items-center justify-end",
209
+ children: [/* @__PURE__ */ jsx("button", {
210
+ type: "button",
211
+ "aria-label": "Row actions",
212
+ "aria-expanded": isMenuOpen,
213
+ "aria-haspopup": "menu",
214
+ onMouseDown: (e) => e.nativeEvent.stopImmediatePropagation(),
215
+ onClick: (e) => {
216
+ e.stopPropagation();
217
+ if (isMenuOpen) setOpenMenuId(null);
218
+ else {
219
+ const rect = e.currentTarget.getBoundingClientRect();
220
+ openMenu(id, {
221
+ top: rect.bottom + 4,
222
+ right: window.innerWidth - rect.right
223
+ });
224
+ }
225
+ },
226
+ className: `
227
+ p-1.5 rounded flex items-center justify-center transition-colors
228
+ ${isMenuOpen ? "bg-login-500 text-login-75" : "text-login-300 hover:bg-login-500/60 hover:text-login-75"}
229
+ `,
230
+ children: /* @__PURE__ */ jsx(EllipsisVertical, { className: "h-4 w-4" })
231
+ }), isMenuOpen && anchor && /* @__PURE__ */ jsx(Menu, {
232
+ ref: menuRef,
233
+ anchor,
234
+ onClose: closeMenu,
235
+ children: menuItems(row, id)
236
+ })]
237
+ })
238
+ })
239
+ ]
240
+ }), hasExpand && isExpanded && /* @__PURE__ */ jsx("tr", {
241
+ className: "bg-login-700/25",
242
+ children: /* @__PURE__ */ jsx("td", {
243
+ colSpan: 999,
244
+ className: "px-6 py-4 border-b border-login-600/20",
245
+ onClick: (e) => e.stopPropagation(),
246
+ children: expandedContent
247
+ })
248
+ })] }, id + rowIdx);
249
+ })
250
+ });
251
+ }
252
+ //#endregion
253
+ export { Body as default };
@@ -0,0 +1,58 @@
1
+ //#region src/components/table/constants.ts
2
+ const HIGHLIGHT = {
3
+ green: "bg-green-500/15 text-green-400 ring-1 ring-green-500/25",
4
+ yellow: "bg-yellow-500/15 text-yellow-400 ring-1 ring-yellow-500/25",
5
+ red: "bg-red-500/15 text-red-400 ring-1 ring-red-500/25",
6
+ blue: "bg-blue-500/15 text-blue-400 ring-1 ring-blue-500/25",
7
+ gray: "bg-gray-500/15 text-gray-400 ring-1 ring-gray-500/25",
8
+ orange: "bg-orange-500/15 text-orange-400 ring-1 ring-orange-500/25",
9
+ purple: "bg-purple-500/15 text-purple-400 ring-1 ring-purple-500/25"
10
+ };
11
+ const DENSITY_TH = {
12
+ compact: "px-4 py-2",
13
+ comfortable: "px-6 py-3",
14
+ spacious: "px-8 py-4"
15
+ };
16
+ const DENSITY_TD = {
17
+ compact: "px-4 py-1.5",
18
+ comfortable: "px-6 py-3.5",
19
+ spacious: "px-8 py-5"
20
+ };
21
+ const VARIANT_CONTAINER = {
22
+ original: "bg-login-500/50 rounded-lg border border-login-600 shadow",
23
+ modern: "bg-transparent"
24
+ };
25
+ const VARIANT_THEAD = {
26
+ original: "bg-login-700",
27
+ modern: "bg-transparent"
28
+ };
29
+ const VARIANT_HEAD_BG = {
30
+ original: "bg-login-700",
31
+ modern: ""
32
+ };
33
+ const VARIANT_HEAD_BORDER = {
34
+ original: "border-b border-login-600",
35
+ modern: "border-b border-login-500/40"
36
+ };
37
+ const VARIANT_ROW_BORDER = {
38
+ original: "border-b border-login-600",
39
+ modern: "border-b border-login-600/15"
40
+ };
41
+ const VARIANT_THEAD_TH = {
42
+ original: "text-login-200",
43
+ modern: "text-login-300"
44
+ };
45
+ const VARIANT_TBODY = {
46
+ original: "bg-login-500/50 divide-login-600",
47
+ modern: "divide-login-600/15"
48
+ };
49
+ const VARIANT_ROW_HOVER = {
50
+ original: "hover:bg-login-600/30",
51
+ modern: "hover:bg-login-700/50"
52
+ };
53
+ const VARIANT_ROW_STRIPED = {
54
+ original: "even:bg-login-600/40",
55
+ modern: "even:bg-login-800/40"
56
+ };
57
+ //#endregion
58
+ export { DENSITY_TD, DENSITY_TH, HIGHLIGHT, VARIANT_CONTAINER, VARIANT_HEAD_BG, VARIANT_HEAD_BORDER, VARIANT_ROW_BORDER, VARIANT_ROW_HOVER, VARIANT_ROW_STRIPED, VARIANT_TBODY, VARIANT_THEAD, VARIANT_THEAD_TH };
@@ -0,0 +1,24 @@
1
+ import { TableIcon } from "lucide-react";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/components/table/empty.tsx
4
+ function Empty({ emptyState }) {
5
+ if (emptyState) return /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
6
+ colSpan: 999,
7
+ children: /* @__PURE__ */ jsx("div", {
8
+ className: "flex items-center justify-center min-h-[160px] py-8 px-6",
9
+ children: emptyState
10
+ })
11
+ }) }) });
12
+ return /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
13
+ colSpan: 999,
14
+ children: /* @__PURE__ */ jsxs("div", {
15
+ className: "flex flex-col items-center justify-center gap-3 min-h-[160px] py-8 text-login-300",
16
+ children: [/* @__PURE__ */ jsx(TableIcon, { className: "h-10 w-10 opacity-30" }), /* @__PURE__ */ jsx("span", {
17
+ className: "text-sm",
18
+ children: "No data found"
19
+ })]
20
+ })
21
+ }) }) });
22
+ }
23
+ //#endregion
24
+ export { Empty as default };