uibee 3.2.0 → 3.3.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.
|
@@ -824,17 +824,21 @@ type SidebarItem = {
|
|
|
824
824
|
};
|
|
825
825
|
type SidebarProps = {
|
|
826
826
|
items: SidebarItem[];
|
|
827
|
-
header?: ReactNode;
|
|
827
|
+
header?: ReactNode | ((expanded: boolean) => ReactNode);
|
|
828
828
|
bottomAction?: (expanded: boolean) => ReactNode;
|
|
829
829
|
mobile?: boolean;
|
|
830
830
|
initialExpanded?: boolean;
|
|
831
|
+
onExpandedChange?: (expanded: boolean) => void;
|
|
832
|
+
className?: string;
|
|
831
833
|
};
|
|
832
834
|
declare function Sidebar({
|
|
833
835
|
items,
|
|
834
836
|
header,
|
|
835
837
|
bottomAction,
|
|
836
838
|
mobile,
|
|
837
|
-
initialExpanded
|
|
839
|
+
initialExpanded,
|
|
840
|
+
onExpandedChange,
|
|
841
|
+
className
|
|
838
842
|
}: SidebarProps): import("react").JSX.Element;
|
|
839
843
|
//#endregion
|
|
840
844
|
//#region src/components/badge/badge.d.ts
|
|
@@ -2054,11 +2054,18 @@ function Footer({ logo, sponsor, columns, socialLinks, copyright, version, lang
|
|
|
2054
2054
|
children: [/* @__PURE__ */ jsx("h4", {
|
|
2055
2055
|
className: "pb-2 text-sm font-medium tracking-widest text-login-100",
|
|
2056
2056
|
children: t(col.heading, lang)
|
|
2057
|
-
}), col.items.map((item, j) => item.href ? /* @__PURE__ */ jsx(
|
|
2058
|
-
className: "link--underscore-hover block",
|
|
2057
|
+
}), col.items.map((item, j) => item.href ? item.href.startsWith("/") ? /* @__PURE__ */ jsx(Link, {
|
|
2058
|
+
className: "link--underscore-hover block text-login-100",
|
|
2059
2059
|
href: item.href,
|
|
2060
2060
|
children: t(item.label, lang)
|
|
2061
|
-
}, j) : /* @__PURE__ */ jsx("
|
|
2061
|
+
}, j) : /* @__PURE__ */ jsx("a", {
|
|
2062
|
+
className: "link--underscore-hover block text-login-100",
|
|
2063
|
+
href: item.href,
|
|
2064
|
+
children: t(item.label, lang)
|
|
2065
|
+
}, j) : /* @__PURE__ */ jsx("p", {
|
|
2066
|
+
className: "text-login-100",
|
|
2067
|
+
children: t(item.label, lang)
|
|
2068
|
+
}, j))]
|
|
2062
2069
|
}, i))
|
|
2063
2070
|
}),
|
|
2064
2071
|
socialLinks && socialLinks.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
@@ -2081,7 +2088,8 @@ function Footer({ logo, sponsor, columns, socialLinks, copyright, version, lang
|
|
|
2081
2088
|
children: [/* @__PURE__ */ jsxs("p", {
|
|
2082
2089
|
className: "text-xs wrap-break-word text-login-100",
|
|
2083
2090
|
children: [
|
|
2084
|
-
"
|
|
2091
|
+
lang === "no" ? "Opphavsrett" : "Copyright",
|
|
2092
|
+
" © ",
|
|
2085
2093
|
year,
|
|
2086
2094
|
" ",
|
|
2087
2095
|
t(copyright, lang)
|
|
@@ -3948,11 +3956,21 @@ function Modal({ isOpen, onClose, title, children, footer, size = "md" }) {
|
|
|
3948
3956
|
const ITEM_HEIGHT = 48;
|
|
3949
3957
|
const GAP = 4;
|
|
3950
3958
|
const SUB_STRIDE = 40;
|
|
3951
|
-
function Sidebar({ items, header, bottomAction, mobile = false, initialExpanded = true }) {
|
|
3959
|
+
function Sidebar({ items, header, bottomAction, mobile = false, initialExpanded = true, onExpandedChange, className = "" }) {
|
|
3952
3960
|
const [expanded, setExpanded] = useState(initialExpanded);
|
|
3953
3961
|
const pathname = usePathname();
|
|
3962
|
+
const searchParams = useSearchParams();
|
|
3963
|
+
const fullPath = pathname + (searchParams.toString() ? `?${searchParams.toString()}` : "");
|
|
3964
|
+
function toggleExpanded() {
|
|
3965
|
+
const next = !expanded;
|
|
3966
|
+
setExpanded(next);
|
|
3967
|
+
onExpandedChange?.(next);
|
|
3968
|
+
}
|
|
3969
|
+
function isSubActive(sub) {
|
|
3970
|
+
return sub.path.includes("?") ? fullPath.startsWith(sub.path) : pathname === sub.path;
|
|
3971
|
+
}
|
|
3954
3972
|
function isItemActive(item) {
|
|
3955
|
-
return pathname === item.path || !!item.items?.some((sub) => pathname === sub.path || pathname.startsWith(sub.path + "/"));
|
|
3973
|
+
return pathname === item.path || !!item.items?.some((sub) => sub.path.includes("?") ? fullPath.startsWith(sub.path) : pathname === sub.path || pathname.startsWith(sub.path + "/"));
|
|
3956
3974
|
}
|
|
3957
3975
|
const activeIndex = items.findIndex(isItemActive);
|
|
3958
3976
|
const activeOffset = items.slice(0, Math.max(activeIndex, 0)).reduce((acc, item) => acc + ITEM_HEIGHT + (item.items ? GAP : 0) + GAP, 0);
|
|
@@ -3961,6 +3979,7 @@ function Sidebar({ items, header, bottomAction, mobile = false, initialExpanded
|
|
|
3961
3979
|
flex flex-col border-r border-login-100/10 bg-login-900
|
|
3962
3980
|
transition-all duration-300 ease-in-out
|
|
3963
3981
|
${mobile ? "w-full" : `h-full ${expanded ? "w-64" : "w-20"}`}
|
|
3982
|
+
${className}
|
|
3964
3983
|
`,
|
|
3965
3984
|
children: [
|
|
3966
3985
|
!mobile && /* @__PURE__ */ jsxs("div", {
|
|
@@ -3970,9 +3989,9 @@ function Sidebar({ items, header, bottomAction, mobile = false, initialExpanded
|
|
|
3970
3989
|
absolute top-4 flex items-center transition-all duration-300
|
|
3971
3990
|
${expanded ? "left-4 gap-3" : "left-1/2 -translate-x-1/2 gap-0"}
|
|
3972
3991
|
`,
|
|
3973
|
-
children: header
|
|
3992
|
+
children: typeof header === "function" ? header(expanded) : header
|
|
3974
3993
|
}), /* @__PURE__ */ jsx("button", {
|
|
3975
|
-
onClick:
|
|
3994
|
+
onClick: toggleExpanded,
|
|
3976
3995
|
className: `
|
|
3977
3996
|
absolute cursor-pointer rounded-lg p-1.5
|
|
3978
3997
|
text-login-200 transition-all duration-300 hover:bg-login-800
|
|
@@ -3983,7 +4002,7 @@ function Sidebar({ items, header, bottomAction, mobile = false, initialExpanded
|
|
|
3983
4002
|
}),
|
|
3984
4003
|
mobile && /* @__PURE__ */ jsx("div", { className: "h-4" }),
|
|
3985
4004
|
/* @__PURE__ */ jsxs("div", {
|
|
3986
|
-
className: "relative flex flex-1 flex-col gap-1 overflow-x-hidden overflow-y-auto px-3",
|
|
4005
|
+
className: "relative flex flex-1 flex-col gap-1 overflow-x-hidden overflow-y-auto px-3 [scrollbar-width:none]",
|
|
3987
4006
|
children: [activeIndex >= 0 && /* @__PURE__ */ jsx("span", {
|
|
3988
4007
|
"aria-hidden": true,
|
|
3989
4008
|
className: "absolute left-3 right-3 top-0 h-12 rounded-lg bg-login-800 transition-transform duration-300 ease-in-out",
|
|
@@ -3991,7 +4010,7 @@ function Sidebar({ items, header, bottomAction, mobile = false, initialExpanded
|
|
|
3991
4010
|
}), items.map((item, index) => {
|
|
3992
4011
|
const isActive = isItemActive(item);
|
|
3993
4012
|
const Icon = item.icon;
|
|
3994
|
-
const activeSubIndex = item.items ? item.items.findIndex(
|
|
4013
|
+
const activeSubIndex = item.items ? item.items.findIndex(isSubActive) : -1;
|
|
3995
4014
|
return /* @__PURE__ */ jsxs("div", {
|
|
3996
4015
|
className: "flex flex-col gap-1",
|
|
3997
4016
|
children: [/* @__PURE__ */ jsxs(Link, {
|
|
@@ -4038,13 +4057,13 @@ function Sidebar({ items, header, bottomAction, mobile = false, initialExpanded
|
|
|
4038
4057
|
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 ",
|
|
4039
4058
|
style: { transform: `translateY(${activeSubIndex * SUB_STRIDE}px)` }
|
|
4040
4059
|
}), item.items.map((sub, subIndex) => {
|
|
4041
|
-
const
|
|
4060
|
+
const subActive = isSubActive(sub);
|
|
4042
4061
|
return /* @__PURE__ */ jsx(Link, {
|
|
4043
4062
|
href: sub.path,
|
|
4044
4063
|
className: `
|
|
4045
4064
|
relative z-10 rounded-lg p-2 text-sm
|
|
4046
4065
|
transition-all duration-200
|
|
4047
|
-
${
|
|
4066
|
+
${subActive ? "text-login" : "text-login-300 hover:bg-login-800/30 hover:text-login-100"}
|
|
4048
4067
|
`,
|
|
4049
4068
|
children: sub.name
|
|
4050
4069
|
}, `${index}-${subIndex}`);
|
package/dist/style.css
CHANGED
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
|
+
import Link from 'next/link'
|
|
2
3
|
import VersionTag from '@components/version/version'
|
|
3
4
|
|
|
4
5
|
export type Lang = 'no' | 'en'
|
|
@@ -56,7 +57,9 @@ export default function Footer({
|
|
|
56
57
|
<div>
|
|
57
58
|
<div className='block w-full'>{sponsor.node}</div>
|
|
58
59
|
{sponsor.label && (
|
|
59
|
-
<p className='pt-8 text-center text-login-100'>
|
|
60
|
+
<p className='pt-8 text-center text-login-100'>
|
|
61
|
+
{t(sponsor.label, lang)}
|
|
62
|
+
</p>
|
|
60
63
|
)}
|
|
61
64
|
</div>
|
|
62
65
|
)}
|
|
@@ -76,11 +79,27 @@ export default function Footer({
|
|
|
76
79
|
</h4>
|
|
77
80
|
{col.items.map((item, j) =>
|
|
78
81
|
item.href ? (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
item.href.startsWith('/') ? (
|
|
83
|
+
<Link
|
|
84
|
+
key={j}
|
|
85
|
+
className='link--underscore-hover block text-login-100'
|
|
86
|
+
href={item.href}
|
|
87
|
+
>
|
|
88
|
+
{t(item.label, lang)}
|
|
89
|
+
</Link>
|
|
90
|
+
) : (
|
|
91
|
+
<a
|
|
92
|
+
key={j}
|
|
93
|
+
className='link--underscore-hover block text-login-100'
|
|
94
|
+
href={item.href}
|
|
95
|
+
>
|
|
96
|
+
{t(item.label, lang)}
|
|
97
|
+
</a>
|
|
98
|
+
)
|
|
82
99
|
) : (
|
|
83
|
-
<p key={j}
|
|
100
|
+
<p key={j} className='text-login-100'>
|
|
101
|
+
{t(item.label, lang)}
|
|
102
|
+
</p>
|
|
84
103
|
)
|
|
85
104
|
)}
|
|
86
105
|
</div>
|
|
@@ -112,7 +131,7 @@ export default function Footer({
|
|
|
112
131
|
md:grid-cols-[auto_min-content] md:items-end md:gap-8'
|
|
113
132
|
>
|
|
114
133
|
<p className='text-xs wrap-break-word text-login-100'>
|
|
115
|
-
Copyright © {year} {t(copyright, lang)}
|
|
134
|
+
{lang === 'no' ? 'Opphavsrett' : 'Copyright'} © {year} {t(copyright, lang)}
|
|
116
135
|
</p>
|
|
117
136
|
{version && (
|
|
118
137
|
<VersionTag version={version.tag} url={version.href} />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import { useState, type ElementType, type ReactNode } from 'react'
|
|
4
|
-
import { usePathname } from 'next/navigation'
|
|
4
|
+
import { usePathname, useSearchParams } from 'next/navigation'
|
|
5
5
|
import Link from 'next/link'
|
|
6
6
|
import { ChevronLeft, ChevronRight } from 'lucide-react'
|
|
7
7
|
|
|
@@ -20,23 +20,49 @@ export type SidebarItem = {
|
|
|
20
20
|
|
|
21
21
|
type SidebarProps = {
|
|
22
22
|
items: SidebarItem[]
|
|
23
|
-
header?: ReactNode
|
|
23
|
+
header?: ReactNode | ((expanded: boolean) => ReactNode)
|
|
24
24
|
bottomAction?: (expanded: boolean) => ReactNode
|
|
25
25
|
mobile?: boolean
|
|
26
26
|
initialExpanded?: boolean
|
|
27
|
+
onExpandedChange?: (expanded: boolean) => void
|
|
28
|
+
className?: string
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
const ITEM_HEIGHT = 48
|
|
30
32
|
const GAP = 4
|
|
31
33
|
const SUB_STRIDE = 40
|
|
32
34
|
|
|
33
|
-
export default function Sidebar({
|
|
35
|
+
export default function Sidebar({
|
|
36
|
+
items,
|
|
37
|
+
header,
|
|
38
|
+
bottomAction,
|
|
39
|
+
mobile = false,
|
|
40
|
+
initialExpanded = true,
|
|
41
|
+
onExpandedChange,
|
|
42
|
+
className = '',
|
|
43
|
+
}: SidebarProps) {
|
|
34
44
|
const [expanded, setExpanded] = useState(initialExpanded)
|
|
35
45
|
const pathname = usePathname()
|
|
46
|
+
const searchParams = useSearchParams()
|
|
47
|
+
const fullPath = pathname + (searchParams.toString() ? `?${searchParams.toString()}` : '')
|
|
48
|
+
|
|
49
|
+
function toggleExpanded() {
|
|
50
|
+
const next = !expanded
|
|
51
|
+
setExpanded(next)
|
|
52
|
+
onExpandedChange?.(next)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isSubActive(sub: SidebarSubItem) {
|
|
56
|
+
return sub.path.includes('?')
|
|
57
|
+
? fullPath.startsWith(sub.path)
|
|
58
|
+
: pathname === sub.path
|
|
59
|
+
}
|
|
36
60
|
|
|
37
61
|
function isItemActive(item: SidebarItem) {
|
|
38
62
|
return pathname === item.path ||
|
|
39
|
-
!!(item.items?.some(sub =>
|
|
63
|
+
!!(item.items?.some(sub => sub.path.includes('?')
|
|
64
|
+
? fullPath.startsWith(sub.path)
|
|
65
|
+
: pathname === sub.path || pathname.startsWith(sub.path + '/')))
|
|
40
66
|
}
|
|
41
67
|
|
|
42
68
|
const activeIndex = items.findIndex(isItemActive)
|
|
@@ -49,6 +75,7 @@ export default function Sidebar({ items, header, bottomAction, mobile = false, i
|
|
|
49
75
|
flex flex-col border-r border-login-100/10 bg-login-900
|
|
50
76
|
transition-all duration-300 ease-in-out
|
|
51
77
|
${mobile ? 'w-full' : `h-full ${expanded ? 'w-64' : 'w-20'}`}
|
|
78
|
+
${className}
|
|
52
79
|
`}>
|
|
53
80
|
{!mobile && (
|
|
54
81
|
<div className={`relative mb-2 p-4 transition-all duration-300 ${expanded ? 'h-16' : 'h-20'}`}>
|
|
@@ -57,11 +84,11 @@ export default function Sidebar({ items, header, bottomAction, mobile = false, i
|
|
|
57
84
|
absolute top-4 flex items-center transition-all duration-300
|
|
58
85
|
${expanded ? 'left-4 gap-3' : 'left-1/2 -translate-x-1/2 gap-0'}
|
|
59
86
|
`}>
|
|
60
|
-
{header}
|
|
87
|
+
{typeof header === 'function' ? header(expanded) : header}
|
|
61
88
|
</div>
|
|
62
89
|
)}
|
|
63
90
|
<button
|
|
64
|
-
onClick={
|
|
91
|
+
onClick={toggleExpanded}
|
|
65
92
|
className={`
|
|
66
93
|
absolute cursor-pointer rounded-lg p-1.5
|
|
67
94
|
text-login-200 transition-all duration-300 hover:bg-login-800
|
|
@@ -75,7 +102,7 @@ export default function Sidebar({ items, header, bottomAction, mobile = false, i
|
|
|
75
102
|
|
|
76
103
|
{mobile && <div className='h-4' />}
|
|
77
104
|
|
|
78
|
-
<div className='relative flex flex-1 flex-col gap-1 overflow-x-hidden overflow-y-auto px-3'>
|
|
105
|
+
<div className='relative flex flex-1 flex-col gap-1 overflow-x-hidden overflow-y-auto px-3 [scrollbar-width:none]'>
|
|
79
106
|
{activeIndex >= 0 && (
|
|
80
107
|
<span
|
|
81
108
|
aria-hidden
|
|
@@ -87,7 +114,7 @@ export default function Sidebar({ items, header, bottomAction, mobile = false, i
|
|
|
87
114
|
const isActive = isItemActive(item)
|
|
88
115
|
const Icon = item.icon
|
|
89
116
|
const activeSubIndex = item.items
|
|
90
|
-
? item.items.findIndex(
|
|
117
|
+
? item.items.findIndex(isSubActive)
|
|
91
118
|
: -1
|
|
92
119
|
|
|
93
120
|
return (
|
|
@@ -142,7 +169,7 @@ export default function Sidebar({ items, header, bottomAction, mobile = false, i
|
|
|
142
169
|
/>
|
|
143
170
|
)}
|
|
144
171
|
{item.items.map((sub, subIndex) => {
|
|
145
|
-
const
|
|
172
|
+
const subActive = isSubActive(sub)
|
|
146
173
|
return (
|
|
147
174
|
<Link
|
|
148
175
|
key={`${index}-${subIndex}`}
|
|
@@ -150,7 +177,7 @@ export default function Sidebar({ items, header, bottomAction, mobile = false, i
|
|
|
150
177
|
className={`
|
|
151
178
|
relative z-10 rounded-lg p-2 text-sm
|
|
152
179
|
transition-all duration-200
|
|
153
|
-
${
|
|
180
|
+
${subActive
|
|
154
181
|
? 'text-login'
|
|
155
182
|
: 'text-login-300 hover:bg-login-800/30 hover:text-login-100'
|
|
156
183
|
}
|