@djangocfg/ui-core 2.1.320 → 2.1.322
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -473
- package/package.json +4 -4
- package/src/components/index.ts +51 -0
- package/src/components/navigation/breadcrumb/breadcrumb-navigation.tsx +127 -0
- package/src/components/navigation/breadcrumb/breadcrumb.tsx +133 -0
- package/src/components/navigation/breadcrumb/index.ts +15 -0
- package/src/components/navigation/pagination/index.ts +18 -0
- package/src/components/navigation/pagination/pagination-static.tsx +249 -0
- package/src/components/navigation/pagination/pagination.tsx +139 -0
- package/src/components/navigation/pagination/ssr-pagination.tsx +176 -0
- package/src/components/navigation/sidebar/index.ts +26 -0
- package/src/components/navigation/sidebar/sidebar.tsx +895 -0
- package/src/components/select/README.md +2 -0
- package/src/components/select/select.tsx +39 -3
- package/src/lib/configurator-schema.ts +105 -0
- package/src/lib/index.ts +7 -0
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { cva, VariantProps } from 'class-variance-authority';
|
|
4
|
+
import { Menu, PanelLeft } from 'lucide-react';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
|
|
7
|
+
import { cn } from '../../../lib';
|
|
8
|
+
import { useIsMobile } from '../../../hooks/media';
|
|
9
|
+
import { useShortcutModLabel } from '../../../hooks/device';
|
|
10
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
11
|
+
|
|
12
|
+
import { Button } from '../../forms/button';
|
|
13
|
+
import { Input } from '../../forms/input';
|
|
14
|
+
import { Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle } from '../../overlay/drawer';
|
|
15
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../overlay/tooltip';
|
|
16
|
+
import { Separator } from '../../layout/separator';
|
|
17
|
+
import { Skeleton } from '../../layout/skeleton';
|
|
18
|
+
import { Link } from '../link';
|
|
19
|
+
|
|
20
|
+
const SIDEBAR_COOKIE_NAME = "sidebar_state"
|
|
21
|
+
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
|
22
|
+
const SIDEBAR_WIDTH = "16rem"
|
|
23
|
+
const SIDEBAR_WIDTH_ICON = "3rem"
|
|
24
|
+
const SIDEBAR_KEYBOARD_SHORTCUT = "b"
|
|
25
|
+
|
|
26
|
+
type SidebarContextProps = {
|
|
27
|
+
state: "expanded" | "collapsed"
|
|
28
|
+
open: boolean
|
|
29
|
+
setOpen: (open: boolean) => void
|
|
30
|
+
openMobile: boolean
|
|
31
|
+
setOpenMobile: (open: boolean) => void
|
|
32
|
+
isMobile: boolean
|
|
33
|
+
toggleSidebar: () => void
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const SidebarContext = React.createContext<SidebarContextProps | null>(null)
|
|
37
|
+
|
|
38
|
+
function useSidebar() {
|
|
39
|
+
const context = React.useContext(SidebarContext)
|
|
40
|
+
if (!context) {
|
|
41
|
+
throw new Error("useSidebar must be used within a SidebarProvider.")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return context
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const SidebarProvider = React.forwardRef<
|
|
48
|
+
HTMLDivElement,
|
|
49
|
+
React.ComponentProps<"div"> & {
|
|
50
|
+
defaultOpen?: boolean
|
|
51
|
+
open?: boolean
|
|
52
|
+
onOpenChange?: (open: boolean) => void
|
|
53
|
+
}
|
|
54
|
+
>(
|
|
55
|
+
(
|
|
56
|
+
{
|
|
57
|
+
defaultOpen = true,
|
|
58
|
+
open: openProp,
|
|
59
|
+
onOpenChange: setOpenProp,
|
|
60
|
+
className,
|
|
61
|
+
style,
|
|
62
|
+
children,
|
|
63
|
+
...props
|
|
64
|
+
},
|
|
65
|
+
ref
|
|
66
|
+
) => {
|
|
67
|
+
const isMobile = useIsMobile()
|
|
68
|
+
const [openMobile, setOpenMobile] = React.useState(false)
|
|
69
|
+
|
|
70
|
+
const [_open, _setOpen] = React.useState(defaultOpen)
|
|
71
|
+
const open = openProp ?? _open
|
|
72
|
+
const setOpen = React.useCallback(
|
|
73
|
+
(value: boolean | ((value: boolean) => boolean)) => {
|
|
74
|
+
const openState = typeof value === "function" ? value(open) : value
|
|
75
|
+
if (setOpenProp) {
|
|
76
|
+
setOpenProp(openState)
|
|
77
|
+
} else {
|
|
78
|
+
_setOpen(openState)
|
|
79
|
+
}
|
|
80
|
+
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
|
81
|
+
},
|
|
82
|
+
[setOpenProp, open]
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
const toggleSidebar = React.useCallback(() => {
|
|
86
|
+
return isMobile
|
|
87
|
+
? setOpenMobile((open) => !open)
|
|
88
|
+
: setOpen((open) => !open)
|
|
89
|
+
}, [isMobile, setOpen, setOpenMobile])
|
|
90
|
+
|
|
91
|
+
React.useEffect(() => {
|
|
92
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
93
|
+
if (
|
|
94
|
+
event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
|
|
95
|
+
(event.metaKey || event.ctrlKey)
|
|
96
|
+
) {
|
|
97
|
+
event.preventDefault()
|
|
98
|
+
toggleSidebar()
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
window.addEventListener("keydown", handleKeyDown)
|
|
103
|
+
return () => window.removeEventListener("keydown", handleKeyDown)
|
|
104
|
+
}, [toggleSidebar])
|
|
105
|
+
|
|
106
|
+
const state = open ? "expanded" : "collapsed"
|
|
107
|
+
|
|
108
|
+
const contextValue = React.useMemo<SidebarContextProps>(
|
|
109
|
+
() => ({
|
|
110
|
+
state,
|
|
111
|
+
open,
|
|
112
|
+
setOpen,
|
|
113
|
+
isMobile,
|
|
114
|
+
openMobile,
|
|
115
|
+
setOpenMobile,
|
|
116
|
+
toggleSidebar,
|
|
117
|
+
}),
|
|
118
|
+
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<SidebarContext.Provider value={contextValue}>
|
|
123
|
+
<TooltipProvider delayDuration={0}>
|
|
124
|
+
<div
|
|
125
|
+
style={
|
|
126
|
+
{
|
|
127
|
+
"--sidebar-width": SIDEBAR_WIDTH,
|
|
128
|
+
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
|
|
129
|
+
...style,
|
|
130
|
+
} as React.CSSProperties
|
|
131
|
+
}
|
|
132
|
+
className={cn(
|
|
133
|
+
"group/sidebar-wrapper flex min-h-svh w-full has-[&_[data-variant=inset]]:bg-sidebar",
|
|
134
|
+
className
|
|
135
|
+
)}
|
|
136
|
+
ref={ref}
|
|
137
|
+
{...props}
|
|
138
|
+
>
|
|
139
|
+
{children}
|
|
140
|
+
</div>
|
|
141
|
+
</TooltipProvider>
|
|
142
|
+
</SidebarContext.Provider>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
SidebarProvider.displayName = "SidebarProvider"
|
|
147
|
+
|
|
148
|
+
const Sidebar = React.forwardRef<
|
|
149
|
+
HTMLDivElement,
|
|
150
|
+
React.ComponentProps<"div"> & {
|
|
151
|
+
side?: "left" | "right"
|
|
152
|
+
variant?: "sidebar" | "floating" | "inset"
|
|
153
|
+
collapsible?: "offcanvas" | "icon" | "none"
|
|
154
|
+
}
|
|
155
|
+
>(
|
|
156
|
+
(
|
|
157
|
+
{
|
|
158
|
+
side = "left",
|
|
159
|
+
variant = "sidebar",
|
|
160
|
+
collapsible = "offcanvas",
|
|
161
|
+
className,
|
|
162
|
+
children,
|
|
163
|
+
...props
|
|
164
|
+
},
|
|
165
|
+
ref
|
|
166
|
+
) => {
|
|
167
|
+
const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
|
|
168
|
+
|
|
169
|
+
if (collapsible === "none") {
|
|
170
|
+
return (
|
|
171
|
+
<div
|
|
172
|
+
className={cn(
|
|
173
|
+
"flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground",
|
|
174
|
+
className
|
|
175
|
+
)}
|
|
176
|
+
ref={ref}
|
|
177
|
+
{...props}
|
|
178
|
+
>
|
|
179
|
+
{children}
|
|
180
|
+
</div>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (isMobile) {
|
|
185
|
+
const drawerSide = side === "right" ? "right" : "left"
|
|
186
|
+
return (
|
|
187
|
+
<div ref={ref} className={cn("contents", className)} {...props}>
|
|
188
|
+
<Drawer
|
|
189
|
+
open={openMobile}
|
|
190
|
+
onOpenChange={setOpenMobile}
|
|
191
|
+
direction={drawerSide}
|
|
192
|
+
shouldScaleBackground={false}
|
|
193
|
+
>
|
|
194
|
+
<DrawerContent
|
|
195
|
+
direction={drawerSide}
|
|
196
|
+
data-sidebar="sidebar"
|
|
197
|
+
data-mobile="true"
|
|
198
|
+
className={cn(
|
|
199
|
+
"flex h-[100dvh] max-h-[100dvh] min-h-0 !w-[min(80vw,320px)] max-w-[min(80vw,320px)] flex-col gap-0 border-sidebar-border/60 p-0 text-sidebar-foreground shadow-xl",
|
|
200
|
+
drawerSide === "left" ? "border-r" : "border-l",
|
|
201
|
+
)}
|
|
202
|
+
style={
|
|
203
|
+
{
|
|
204
|
+
backgroundColor: "hsl(var(--sidebar-background))",
|
|
205
|
+
} as React.CSSProperties
|
|
206
|
+
}
|
|
207
|
+
>
|
|
208
|
+
<DrawerHeader className="sr-only">
|
|
209
|
+
<DrawerTitle>Sidebar</DrawerTitle>
|
|
210
|
+
<DrawerDescription>Mobile navigation sidebar.</DrawerDescription>
|
|
211
|
+
</DrawerHeader>
|
|
212
|
+
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">{children}</div>
|
|
213
|
+
</DrawerContent>
|
|
214
|
+
</Drawer>
|
|
215
|
+
</div>
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const getGapWidth = () => {
|
|
220
|
+
if (state === "collapsed") {
|
|
221
|
+
if (collapsible === "offcanvas") return "0"
|
|
222
|
+
if (collapsible === "icon") {
|
|
223
|
+
return variant === "floating" || variant === "inset"
|
|
224
|
+
? "calc(var(--sidebar-width-icon) + 1rem)"
|
|
225
|
+
: "var(--sidebar-width-icon)"
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return "var(--sidebar-width)"
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const getFixedWidth = () => {
|
|
232
|
+
if (state === "collapsed" && collapsible === "icon") {
|
|
233
|
+
return variant === "floating" || variant === "inset"
|
|
234
|
+
? "calc(var(--sidebar-width-icon) + 1rem + 2px)"
|
|
235
|
+
: "var(--sidebar-width-icon)"
|
|
236
|
+
}
|
|
237
|
+
return "var(--sidebar-width)"
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<div
|
|
242
|
+
ref={ref}
|
|
243
|
+
className="group peer hidden text-sidebar-foreground md:block"
|
|
244
|
+
data-state={state}
|
|
245
|
+
data-collapsible={collapsible}
|
|
246
|
+
data-variant={variant}
|
|
247
|
+
data-side={side}
|
|
248
|
+
>
|
|
249
|
+
<div
|
|
250
|
+
className={cn(
|
|
251
|
+
"relative h-full bg-transparent transition-[width] duration-200 ease-linear",
|
|
252
|
+
side === "right" && "rotate-180"
|
|
253
|
+
)}
|
|
254
|
+
style={{
|
|
255
|
+
width: getGapWidth()
|
|
256
|
+
}}
|
|
257
|
+
/>
|
|
258
|
+
<div
|
|
259
|
+
className={cn(
|
|
260
|
+
"fixed inset-y-0 z-10 hidden h-svh transition-[left,right,width] duration-200 ease-linear md:flex",
|
|
261
|
+
side === "left"
|
|
262
|
+
? state === "collapsed" && collapsible === "offcanvas"
|
|
263
|
+
? "left-[calc(var(--sidebar-width)*-1)]"
|
|
264
|
+
: "left-0"
|
|
265
|
+
: state === "collapsed" && collapsible === "offcanvas"
|
|
266
|
+
? "right-[calc(var(--sidebar-width)*-1)]"
|
|
267
|
+
: "right-0",
|
|
268
|
+
variant === "floating" || variant === "inset"
|
|
269
|
+
? "p-2"
|
|
270
|
+
: undefined,
|
|
271
|
+
className
|
|
272
|
+
)}
|
|
273
|
+
style={{
|
|
274
|
+
width: getFixedWidth()
|
|
275
|
+
}}
|
|
276
|
+
{...props}
|
|
277
|
+
>
|
|
278
|
+
<div
|
|
279
|
+
data-sidebar="sidebar"
|
|
280
|
+
className={cn(
|
|
281
|
+
"relative flex h-full w-full flex-col overflow-hidden text-sidebar-foreground",
|
|
282
|
+
variant === "floating"
|
|
283
|
+
? "rounded-lg border border-sidebar-border bg-sidebar shadow"
|
|
284
|
+
: "bg-sidebar",
|
|
285
|
+
)}
|
|
286
|
+
>
|
|
287
|
+
{variant === "sidebar" && (
|
|
288
|
+
<div
|
|
289
|
+
aria-hidden
|
|
290
|
+
className={cn(
|
|
291
|
+
"pointer-events-none absolute inset-y-0 right-0 z-[1] w-px",
|
|
292
|
+
"bg-[linear-gradient(180deg,hsl(var(--sidebar-border)_/_0.02)_0%,hsl(var(--sidebar-border)_/_0.22)_18%,hsl(var(--sidebar-border)_/_0.4)_50%,hsl(var(--sidebar-border)_/_0.2)_82%,hsl(var(--sidebar-border)_/_0.03)_100%)]",
|
|
293
|
+
"dark:bg-[linear-gradient(180deg,hsl(var(--sidebar-border)_/_0.08)_0%,hsl(var(--sidebar-border)_/_0.34)_22%,hsl(var(--sidebar-border)_/_0.55)_50%,hsl(var(--sidebar-border)_/_0.28)_78%,hsl(var(--sidebar-border)_/_0.06)_100%)]"
|
|
294
|
+
)}
|
|
295
|
+
/>
|
|
296
|
+
)}
|
|
297
|
+
<div className="relative z-0 flex min-h-0 flex-1 flex-col">{children}</div>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
)
|
|
304
|
+
Sidebar.displayName = "Sidebar"
|
|
305
|
+
|
|
306
|
+
const SidebarTrigger = React.forwardRef<
|
|
307
|
+
React.ElementRef<typeof Button>,
|
|
308
|
+
React.ComponentProps<typeof Button>
|
|
309
|
+
>(({ className, onClick, ...props }, ref) => {
|
|
310
|
+
const { toggleSidebar, openMobile } = useSidebar()
|
|
311
|
+
const mod = useShortcutModLabel()
|
|
312
|
+
const isMobile = useIsMobile()
|
|
313
|
+
const desktopHint = `Toggle sidebar (${mod}+B)`
|
|
314
|
+
|
|
315
|
+
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
316
|
+
onClick?.(event)
|
|
317
|
+
toggleSidebar()
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const buttonClass = cn("h-7 w-7", className)
|
|
321
|
+
|
|
322
|
+
if (isMobile) {
|
|
323
|
+
return (
|
|
324
|
+
<Button
|
|
325
|
+
ref={ref}
|
|
326
|
+
data-sidebar="trigger"
|
|
327
|
+
variant="ghost"
|
|
328
|
+
size="icon"
|
|
329
|
+
className={buttonClass}
|
|
330
|
+
onClick={handleClick}
|
|
331
|
+
{...props}
|
|
332
|
+
>
|
|
333
|
+
<Menu className="h-4 w-4" />
|
|
334
|
+
<span className="sr-only">{openMobile ? "Close menu" : "Open menu"}</span>
|
|
335
|
+
</Button>
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return (
|
|
340
|
+
<Tooltip delayDuration={400}>
|
|
341
|
+
<TooltipTrigger asChild>
|
|
342
|
+
<Button
|
|
343
|
+
ref={ref}
|
|
344
|
+
data-sidebar="trigger"
|
|
345
|
+
variant="ghost"
|
|
346
|
+
size="icon"
|
|
347
|
+
className={buttonClass}
|
|
348
|
+
onClick={handleClick}
|
|
349
|
+
{...props}
|
|
350
|
+
>
|
|
351
|
+
<PanelLeft className="h-4 w-4" />
|
|
352
|
+
<span className="sr-only">{desktopHint}</span>
|
|
353
|
+
</Button>
|
|
354
|
+
</TooltipTrigger>
|
|
355
|
+
<TooltipContent side="right" align="center" sideOffset={8} className="max-w-[16rem]">
|
|
356
|
+
{desktopHint}
|
|
357
|
+
</TooltipContent>
|
|
358
|
+
</Tooltip>
|
|
359
|
+
)
|
|
360
|
+
})
|
|
361
|
+
SidebarTrigger.displayName = "SidebarTrigger"
|
|
362
|
+
|
|
363
|
+
const SidebarRail = React.forwardRef<
|
|
364
|
+
HTMLButtonElement,
|
|
365
|
+
React.ComponentProps<"button">
|
|
366
|
+
>(({ className, ...props }, ref) => {
|
|
367
|
+
const { toggleSidebar } = useSidebar()
|
|
368
|
+
|
|
369
|
+
return (
|
|
370
|
+
<button
|
|
371
|
+
ref={ref}
|
|
372
|
+
data-sidebar="rail"
|
|
373
|
+
aria-label="Toggle Sidebar"
|
|
374
|
+
tabIndex={-1}
|
|
375
|
+
onClick={toggleSidebar}
|
|
376
|
+
className={cn(
|
|
377
|
+
"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
|
|
378
|
+
"group-data-[side=left]:cursor-w-resize group-data-[side=right]:cursor-e-resize",
|
|
379
|
+
"group-data-[side=left]:group-data-[state=collapsed]:cursor-e-resize group-data-[side=right]:group-data-[state=collapsed]:cursor-w-resize",
|
|
380
|
+
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar",
|
|
381
|
+
"group-data-[side=left]:group-data-[collapsible=offcanvas]:-right-2",
|
|
382
|
+
"group-data-[side=right]:group-data-[collapsible=offcanvas]:-left-2",
|
|
383
|
+
className
|
|
384
|
+
)}
|
|
385
|
+
{...props}
|
|
386
|
+
/>
|
|
387
|
+
)
|
|
388
|
+
})
|
|
389
|
+
SidebarRail.displayName = "SidebarRail"
|
|
390
|
+
|
|
391
|
+
const SidebarInset = React.forwardRef<
|
|
392
|
+
HTMLDivElement,
|
|
393
|
+
React.ComponentProps<"main">
|
|
394
|
+
>(({ className, ...props }, ref) => {
|
|
395
|
+
return (
|
|
396
|
+
<main
|
|
397
|
+
ref={ref}
|
|
398
|
+
className={cn(
|
|
399
|
+
"relative flex w-full flex-1 flex-col bg-background",
|
|
400
|
+
"md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
|
|
401
|
+
className
|
|
402
|
+
)}
|
|
403
|
+
{...props}
|
|
404
|
+
/>
|
|
405
|
+
)
|
|
406
|
+
})
|
|
407
|
+
SidebarInset.displayName = "SidebarInset"
|
|
408
|
+
|
|
409
|
+
const SidebarInput: React.ForwardRefExoticComponent<
|
|
410
|
+
React.ComponentProps<typeof Input> & React.RefAttributes<HTMLInputElement>
|
|
411
|
+
> = React.forwardRef<
|
|
412
|
+
React.ElementRef<typeof Input>,
|
|
413
|
+
React.ComponentProps<typeof Input>
|
|
414
|
+
>(({ className, ...props }, ref) => {
|
|
415
|
+
return (
|
|
416
|
+
<Input
|
|
417
|
+
ref={ref}
|
|
418
|
+
data-sidebar="input"
|
|
419
|
+
className={cn(
|
|
420
|
+
"h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring",
|
|
421
|
+
className
|
|
422
|
+
)}
|
|
423
|
+
{...props}
|
|
424
|
+
/>
|
|
425
|
+
)
|
|
426
|
+
})
|
|
427
|
+
SidebarInput.displayName = "SidebarInput"
|
|
428
|
+
|
|
429
|
+
const SidebarHeader = React.forwardRef<
|
|
430
|
+
HTMLDivElement,
|
|
431
|
+
React.ComponentProps<"div">
|
|
432
|
+
>(({ className, style, ...props }, ref) => {
|
|
433
|
+
const { state, isMobile } = useSidebar()
|
|
434
|
+
|
|
435
|
+
const headerStyle = state === "collapsed" && !isMobile ? {
|
|
436
|
+
paddingLeft: '0',
|
|
437
|
+
paddingRight: '0',
|
|
438
|
+
paddingTop: '0.5rem',
|
|
439
|
+
paddingBottom: '0.5rem',
|
|
440
|
+
transition: 'padding 200ms ease-in-out',
|
|
441
|
+
...style
|
|
442
|
+
} : {
|
|
443
|
+
transition: 'padding 200ms ease-in-out',
|
|
444
|
+
...style
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return (
|
|
448
|
+
<div
|
|
449
|
+
ref={ref}
|
|
450
|
+
data-sidebar="header"
|
|
451
|
+
className={cn("flex flex-col gap-2 p-2", className)}
|
|
452
|
+
style={headerStyle}
|
|
453
|
+
{...props}
|
|
454
|
+
/>
|
|
455
|
+
)
|
|
456
|
+
})
|
|
457
|
+
SidebarHeader.displayName = "SidebarHeader"
|
|
458
|
+
|
|
459
|
+
const SidebarFooter = React.forwardRef<
|
|
460
|
+
HTMLDivElement,
|
|
461
|
+
React.ComponentProps<"div">
|
|
462
|
+
>(({ className, ...props }, ref) => {
|
|
463
|
+
return (
|
|
464
|
+
<div
|
|
465
|
+
ref={ref}
|
|
466
|
+
data-sidebar="footer"
|
|
467
|
+
className={cn("flex flex-col gap-2 p-2", className)}
|
|
468
|
+
{...props}
|
|
469
|
+
/>
|
|
470
|
+
)
|
|
471
|
+
})
|
|
472
|
+
SidebarFooter.displayName = "SidebarFooter"
|
|
473
|
+
|
|
474
|
+
const SidebarSeparator: React.ForwardRefExoticComponent<
|
|
475
|
+
React.ComponentProps<typeof Separator> & React.RefAttributes<React.ElementRef<typeof Separator>>
|
|
476
|
+
> = React.forwardRef<
|
|
477
|
+
React.ElementRef<typeof Separator>,
|
|
478
|
+
React.ComponentProps<typeof Separator>
|
|
479
|
+
>(({ className, ...props }, ref) => {
|
|
480
|
+
return (
|
|
481
|
+
<Separator
|
|
482
|
+
ref={ref}
|
|
483
|
+
data-sidebar="separator"
|
|
484
|
+
className={cn("mx-2 w-auto bg-sidebar-border", className)}
|
|
485
|
+
{...props}
|
|
486
|
+
/>
|
|
487
|
+
)
|
|
488
|
+
})
|
|
489
|
+
SidebarSeparator.displayName = "SidebarSeparator"
|
|
490
|
+
|
|
491
|
+
const SidebarContent = React.forwardRef<
|
|
492
|
+
HTMLDivElement,
|
|
493
|
+
React.ComponentProps<"div">
|
|
494
|
+
>(({ className, ...props }, ref) => {
|
|
495
|
+
return (
|
|
496
|
+
<div
|
|
497
|
+
ref={ref}
|
|
498
|
+
data-sidebar="content"
|
|
499
|
+
className={cn(
|
|
500
|
+
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[state=collapsed]:group-data-[collapsible=icon]:overflow-hidden",
|
|
501
|
+
className
|
|
502
|
+
)}
|
|
503
|
+
{...props}
|
|
504
|
+
/>
|
|
505
|
+
)
|
|
506
|
+
})
|
|
507
|
+
SidebarContent.displayName = "SidebarContent"
|
|
508
|
+
|
|
509
|
+
const SidebarGroup = React.forwardRef<
|
|
510
|
+
HTMLDivElement,
|
|
511
|
+
React.ComponentProps<"div">
|
|
512
|
+
>(({ className, ...props }, ref) => {
|
|
513
|
+
return (
|
|
514
|
+
<div
|
|
515
|
+
ref={ref}
|
|
516
|
+
data-sidebar="group"
|
|
517
|
+
className={cn("relative flex w-full min-w-0 flex-col p-2", className)}
|
|
518
|
+
{...props}
|
|
519
|
+
/>
|
|
520
|
+
)
|
|
521
|
+
})
|
|
522
|
+
SidebarGroup.displayName = "SidebarGroup"
|
|
523
|
+
|
|
524
|
+
const SidebarGroupLabel = React.forwardRef<
|
|
525
|
+
HTMLDivElement,
|
|
526
|
+
React.ComponentProps<"div"> & { asChild?: boolean }
|
|
527
|
+
>(({ className, asChild = false, ...props }, ref) => {
|
|
528
|
+
const Comp = asChild ? Slot : "div"
|
|
529
|
+
|
|
530
|
+
return (
|
|
531
|
+
<Comp
|
|
532
|
+
ref={ref}
|
|
533
|
+
data-sidebar="group-label"
|
|
534
|
+
className={cn(
|
|
535
|
+
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-semibold text-muted-foreground uppercase tracking-wider outline-none ring-sidebar-ring transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
536
|
+
"group-data-[state=collapsed]:group-data-[collapsible=icon]:pointer-events-none group-data-[state=collapsed]:group-data-[collapsible=icon]:-mt-8 group-data-[state=collapsed]:group-data-[collapsible=icon]:opacity-0",
|
|
537
|
+
className
|
|
538
|
+
)}
|
|
539
|
+
{...props}
|
|
540
|
+
/>
|
|
541
|
+
)
|
|
542
|
+
})
|
|
543
|
+
SidebarGroupLabel.displayName = "SidebarGroupLabel"
|
|
544
|
+
|
|
545
|
+
const SidebarGroupAction = React.forwardRef<
|
|
546
|
+
HTMLButtonElement,
|
|
547
|
+
React.ComponentProps<"button"> & { asChild?: boolean }
|
|
548
|
+
>(({ className, asChild = false, ...props }, ref) => {
|
|
549
|
+
const Comp = asChild ? Slot : "button"
|
|
550
|
+
|
|
551
|
+
return (
|
|
552
|
+
<Comp
|
|
553
|
+
ref={ref}
|
|
554
|
+
data-sidebar="group-action"
|
|
555
|
+
className={cn(
|
|
556
|
+
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
557
|
+
"after:absolute after:-inset-2 after:md:hidden",
|
|
558
|
+
"group-data-[state=collapsed]:group-data-[collapsible=icon]:hidden",
|
|
559
|
+
className
|
|
560
|
+
)}
|
|
561
|
+
{...props}
|
|
562
|
+
/>
|
|
563
|
+
)
|
|
564
|
+
})
|
|
565
|
+
SidebarGroupAction.displayName = "SidebarGroupAction"
|
|
566
|
+
|
|
567
|
+
const SidebarGroupContent = React.forwardRef<
|
|
568
|
+
HTMLDivElement,
|
|
569
|
+
React.ComponentProps<"div">
|
|
570
|
+
>(({ className, ...props }, ref) => (
|
|
571
|
+
<div
|
|
572
|
+
ref={ref}
|
|
573
|
+
data-sidebar="group-content"
|
|
574
|
+
className={cn("w-full text-sm", className)}
|
|
575
|
+
{...props}
|
|
576
|
+
/>
|
|
577
|
+
))
|
|
578
|
+
SidebarGroupContent.displayName = "SidebarGroupContent"
|
|
579
|
+
|
|
580
|
+
const SidebarMenu = React.forwardRef<
|
|
581
|
+
HTMLUListElement,
|
|
582
|
+
React.ComponentProps<"ul">
|
|
583
|
+
>(({ className, ...props }, ref) => (
|
|
584
|
+
<ul
|
|
585
|
+
ref={ref}
|
|
586
|
+
data-sidebar="menu"
|
|
587
|
+
className={cn("flex w-full min-w-0 flex-col gap-1", className)}
|
|
588
|
+
{...props}
|
|
589
|
+
/>
|
|
590
|
+
))
|
|
591
|
+
SidebarMenu.displayName = "SidebarMenu"
|
|
592
|
+
|
|
593
|
+
const SidebarMenuItem = React.forwardRef<
|
|
594
|
+
HTMLLIElement,
|
|
595
|
+
React.ComponentProps<"li">
|
|
596
|
+
>(({ className, ...props }, ref) => (
|
|
597
|
+
<li
|
|
598
|
+
ref={ref}
|
|
599
|
+
data-sidebar="menu-item"
|
|
600
|
+
className={cn("group/menu-item relative", className)}
|
|
601
|
+
{...props}
|
|
602
|
+
/>
|
|
603
|
+
))
|
|
604
|
+
SidebarMenuItem.displayName = "SidebarMenuItem"
|
|
605
|
+
|
|
606
|
+
const sidebarMenuButtonVariants = cva(
|
|
607
|
+
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm font-medium outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[&_[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-semibold data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-muted-foreground [&>svg]:opacity-70 data-[active=true]:[&>svg]:text-sidebar-accent-foreground data-[active=true]:[&>svg]:opacity-100 hover:[&>svg]:text-sidebar-accent-foreground hover:[&>svg]:opacity-100 group-data-[state=collapsed]:group-data-[collapsible=icon]:justify-center group-data-[state=collapsed]:group-data-[collapsible=icon]:[&>span]:hidden",
|
|
608
|
+
{
|
|
609
|
+
variants: {
|
|
610
|
+
variant: {
|
|
611
|
+
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
612
|
+
outline:
|
|
613
|
+
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
|
|
614
|
+
},
|
|
615
|
+
size: {
|
|
616
|
+
default: "h-8 text-sm",
|
|
617
|
+
sm: "h-7 text-xs",
|
|
618
|
+
lg: "h-12 text-sm group-data-[state=collapsed]:group-data-[collapsible=icon]:!p-0",
|
|
619
|
+
},
|
|
620
|
+
},
|
|
621
|
+
defaultVariants: {
|
|
622
|
+
variant: "default",
|
|
623
|
+
size: "default",
|
|
624
|
+
},
|
|
625
|
+
}
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
const SidebarMenuButton = React.forwardRef<
|
|
629
|
+
HTMLButtonElement,
|
|
630
|
+
React.ComponentProps<"button"> & {
|
|
631
|
+
asChild?: boolean
|
|
632
|
+
isActive?: boolean
|
|
633
|
+
tooltip?: string | React.ComponentProps<typeof TooltipContent>
|
|
634
|
+
href?: string
|
|
635
|
+
} & VariantProps<typeof sidebarMenuButtonVariants>
|
|
636
|
+
>(
|
|
637
|
+
(
|
|
638
|
+
{
|
|
639
|
+
asChild = false,
|
|
640
|
+
isActive = false,
|
|
641
|
+
variant = "default",
|
|
642
|
+
size = "default",
|
|
643
|
+
tooltip,
|
|
644
|
+
className,
|
|
645
|
+
style,
|
|
646
|
+
href,
|
|
647
|
+
children,
|
|
648
|
+
...props
|
|
649
|
+
},
|
|
650
|
+
ref
|
|
651
|
+
) => {
|
|
652
|
+
const { isMobile, state } = useSidebar()
|
|
653
|
+
|
|
654
|
+
const buttonContent = React.useMemo(() => {
|
|
655
|
+
if (href) {
|
|
656
|
+
return (
|
|
657
|
+
<Link
|
|
658
|
+
href={href}
|
|
659
|
+
className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
|
|
660
|
+
style={style}
|
|
661
|
+
data-sidebar="menu-button"
|
|
662
|
+
data-size={size}
|
|
663
|
+
data-active={isActive}
|
|
664
|
+
>
|
|
665
|
+
{children}
|
|
666
|
+
</Link>
|
|
667
|
+
)
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const Comp = asChild ? Slot : "button"
|
|
671
|
+
return (
|
|
672
|
+
<Comp
|
|
673
|
+
ref={ref}
|
|
674
|
+
data-sidebar="menu-button"
|
|
675
|
+
data-size={size}
|
|
676
|
+
data-active={isActive}
|
|
677
|
+
className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
|
|
678
|
+
style={style}
|
|
679
|
+
{...props}
|
|
680
|
+
>
|
|
681
|
+
{children}
|
|
682
|
+
</Comp>
|
|
683
|
+
)
|
|
684
|
+
}, [href, asChild, ref, variant, size, className, style, isActive, children, props])
|
|
685
|
+
|
|
686
|
+
if (!tooltip) {
|
|
687
|
+
return buttonContent
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const tooltipContentProps: React.ComponentProps<typeof TooltipContent> =
|
|
691
|
+
typeof tooltip === "string" ? { children: tooltip } : { ...tooltip }
|
|
692
|
+
|
|
693
|
+
return (
|
|
694
|
+
<Tooltip>
|
|
695
|
+
<TooltipTrigger asChild>{buttonContent}</TooltipTrigger>
|
|
696
|
+
<TooltipContent
|
|
697
|
+
side="right"
|
|
698
|
+
align="center"
|
|
699
|
+
sideOffset={8}
|
|
700
|
+
avoidCollisions={false}
|
|
701
|
+
hidden={state !== "collapsed" || isMobile}
|
|
702
|
+
{...tooltipContentProps}
|
|
703
|
+
/>
|
|
704
|
+
</Tooltip>
|
|
705
|
+
)
|
|
706
|
+
}
|
|
707
|
+
)
|
|
708
|
+
SidebarMenuButton.displayName = "SidebarMenuButton"
|
|
709
|
+
|
|
710
|
+
const SidebarMenuAction = React.forwardRef<
|
|
711
|
+
HTMLButtonElement,
|
|
712
|
+
React.ComponentProps<"button"> & {
|
|
713
|
+
asChild?: boolean
|
|
714
|
+
showOnHover?: boolean
|
|
715
|
+
}
|
|
716
|
+
>(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
|
|
717
|
+
const Comp = asChild ? Slot : "button"
|
|
718
|
+
|
|
719
|
+
return (
|
|
720
|
+
<Comp
|
|
721
|
+
ref={ref}
|
|
722
|
+
data-sidebar="menu-action"
|
|
723
|
+
className={cn(
|
|
724
|
+
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
|
|
725
|
+
"after:absolute after:-inset-2 after:md:hidden",
|
|
726
|
+
"peer-data-[size=sm]/menu-button:top-1",
|
|
727
|
+
"peer-data-[size=default]/menu-button:top-1.5",
|
|
728
|
+
"peer-data-[size=lg]/menu-button:top-2.5",
|
|
729
|
+
"group-data-[state=collapsed]:group-data-[collapsible=icon]:hidden",
|
|
730
|
+
showOnHover &&
|
|
731
|
+
"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0",
|
|
732
|
+
className
|
|
733
|
+
)}
|
|
734
|
+
{...props}
|
|
735
|
+
/>
|
|
736
|
+
)
|
|
737
|
+
})
|
|
738
|
+
SidebarMenuAction.displayName = "SidebarMenuAction"
|
|
739
|
+
|
|
740
|
+
const SidebarMenuBadge = React.forwardRef<
|
|
741
|
+
HTMLDivElement,
|
|
742
|
+
React.ComponentProps<"div">
|
|
743
|
+
>(({ className, ...props }, ref) => (
|
|
744
|
+
<div
|
|
745
|
+
ref={ref}
|
|
746
|
+
data-sidebar="menu-badge"
|
|
747
|
+
className={cn(
|
|
748
|
+
"pointer-events-none absolute right-1 flex h-4 min-w-4 select-none items-center justify-center rounded-md px-1 text-[10px] font-medium tabular-nums leading-none text-muted-foreground/75",
|
|
749
|
+
"peer-hover/menu-button:text-muted-foreground peer-data-[active=true]/menu-button:text-foreground/65",
|
|
750
|
+
"peer-data-[size=sm]/menu-button:top-1",
|
|
751
|
+
"peer-data-[size=default]/menu-button:top-1.5",
|
|
752
|
+
"peer-data-[size=lg]/menu-button:top-2",
|
|
753
|
+
"group-data-[state=collapsed]:group-data-[collapsible=icon]:hidden",
|
|
754
|
+
className
|
|
755
|
+
)}
|
|
756
|
+
{...props}
|
|
757
|
+
/>
|
|
758
|
+
))
|
|
759
|
+
SidebarMenuBadge.displayName = "SidebarMenuBadge"
|
|
760
|
+
|
|
761
|
+
const SidebarMenuSkeleton = React.forwardRef<
|
|
762
|
+
HTMLDivElement,
|
|
763
|
+
React.ComponentProps<"div"> & {
|
|
764
|
+
showIcon?: boolean
|
|
765
|
+
}
|
|
766
|
+
>(({ className, showIcon = false, ...props }, ref) => {
|
|
767
|
+
const width = React.useMemo(() => {
|
|
768
|
+
return `${Math.floor(Math.random() * 40) + 50}%`
|
|
769
|
+
}, [])
|
|
770
|
+
|
|
771
|
+
return (
|
|
772
|
+
<div
|
|
773
|
+
ref={ref}
|
|
774
|
+
data-sidebar="menu-skeleton"
|
|
775
|
+
className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
|
|
776
|
+
{...props}
|
|
777
|
+
>
|
|
778
|
+
{showIcon && (
|
|
779
|
+
<Skeleton
|
|
780
|
+
className="size-4 rounded-md"
|
|
781
|
+
data-sidebar="menu-skeleton-icon"
|
|
782
|
+
/>
|
|
783
|
+
)}
|
|
784
|
+
<Skeleton
|
|
785
|
+
className="h-4 max-w-[--skeleton-width] flex-1"
|
|
786
|
+
data-sidebar="menu-skeleton-text"
|
|
787
|
+
style={
|
|
788
|
+
{
|
|
789
|
+
"--skeleton-width": width,
|
|
790
|
+
} as React.CSSProperties
|
|
791
|
+
}
|
|
792
|
+
/>
|
|
793
|
+
</div>
|
|
794
|
+
)
|
|
795
|
+
})
|
|
796
|
+
SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton"
|
|
797
|
+
|
|
798
|
+
const SidebarMenuSub = React.forwardRef<
|
|
799
|
+
HTMLUListElement,
|
|
800
|
+
React.ComponentProps<"ul">
|
|
801
|
+
>(({ className, ...props }, ref) => (
|
|
802
|
+
<ul
|
|
803
|
+
ref={ref}
|
|
804
|
+
data-sidebar="menu-sub"
|
|
805
|
+
className={cn(
|
|
806
|
+
"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5",
|
|
807
|
+
"group-data-[state=collapsed]:group-data-[collapsible=icon]:hidden",
|
|
808
|
+
className
|
|
809
|
+
)}
|
|
810
|
+
{...props}
|
|
811
|
+
/>
|
|
812
|
+
))
|
|
813
|
+
SidebarMenuSub.displayName = "SidebarMenuSub"
|
|
814
|
+
|
|
815
|
+
const SidebarMenuSubItem = React.forwardRef<
|
|
816
|
+
HTMLLIElement,
|
|
817
|
+
React.ComponentProps<"li">
|
|
818
|
+
>(({ ...props }, ref) => <li ref={ref} {...props} />)
|
|
819
|
+
SidebarMenuSubItem.displayName = "SidebarMenuSubItem"
|
|
820
|
+
|
|
821
|
+
const SidebarMenuSubButton = React.forwardRef<
|
|
822
|
+
HTMLAnchorElement,
|
|
823
|
+
React.ComponentProps<"a"> & {
|
|
824
|
+
asChild?: boolean
|
|
825
|
+
size?: "sm" | "md"
|
|
826
|
+
isActive?: boolean
|
|
827
|
+
href?: string
|
|
828
|
+
}
|
|
829
|
+
>(({ asChild = false, size = "md", isActive, className, href, children, ...props }, ref) => {
|
|
830
|
+
const Comp = asChild ? Slot : "a"
|
|
831
|
+
|
|
832
|
+
const buttonClasses = cn(
|
|
833
|
+
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-muted-foreground [&>svg]:opacity-70 data-[active=true]:[&>svg]:text-sidebar-accent-foreground data-[active=true]:[&>svg]:opacity-100 hover:[&>svg]:text-sidebar-accent-foreground hover:[&>svg]:opacity-100",
|
|
834
|
+
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
|
|
835
|
+
size === "sm" && "text-xs",
|
|
836
|
+
size === "md" && "text-sm",
|
|
837
|
+
"group-data-[state=collapsed]:group-data-[collapsible=icon]:hidden",
|
|
838
|
+
className
|
|
839
|
+
)
|
|
840
|
+
|
|
841
|
+
if (href) {
|
|
842
|
+
return (
|
|
843
|
+
<Link
|
|
844
|
+
href={href}
|
|
845
|
+
className={buttonClasses}
|
|
846
|
+
data-sidebar="menu-sub-button"
|
|
847
|
+
data-size={size}
|
|
848
|
+
data-active={isActive}
|
|
849
|
+
>
|
|
850
|
+
{children}
|
|
851
|
+
</Link>
|
|
852
|
+
)
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
return (
|
|
856
|
+
<Comp
|
|
857
|
+
ref={ref}
|
|
858
|
+
data-sidebar="menu-sub-button"
|
|
859
|
+
data-size={size}
|
|
860
|
+
data-active={isActive}
|
|
861
|
+
className={buttonClasses}
|
|
862
|
+
{...props}
|
|
863
|
+
>
|
|
864
|
+
{children}
|
|
865
|
+
</Comp>
|
|
866
|
+
)
|
|
867
|
+
})
|
|
868
|
+
SidebarMenuSubButton.displayName = "SidebarMenuSubButton"
|
|
869
|
+
|
|
870
|
+
export {
|
|
871
|
+
Sidebar,
|
|
872
|
+
SidebarContent,
|
|
873
|
+
SidebarFooter,
|
|
874
|
+
SidebarGroup,
|
|
875
|
+
SidebarGroupAction,
|
|
876
|
+
SidebarGroupContent,
|
|
877
|
+
SidebarGroupLabel,
|
|
878
|
+
SidebarHeader,
|
|
879
|
+
SidebarInput,
|
|
880
|
+
SidebarInset,
|
|
881
|
+
SidebarMenu,
|
|
882
|
+
SidebarMenuAction,
|
|
883
|
+
SidebarMenuBadge,
|
|
884
|
+
SidebarMenuButton,
|
|
885
|
+
SidebarMenuItem,
|
|
886
|
+
SidebarMenuSkeleton,
|
|
887
|
+
SidebarMenuSub,
|
|
888
|
+
SidebarMenuSubButton,
|
|
889
|
+
SidebarMenuSubItem,
|
|
890
|
+
SidebarProvider,
|
|
891
|
+
SidebarRail,
|
|
892
|
+
SidebarSeparator,
|
|
893
|
+
SidebarTrigger,
|
|
894
|
+
useSidebar,
|
|
895
|
+
}
|