@vendure/dashboard 3.3.6-master-202507030835 → 3.3.6-master-202507031127

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 (51) hide show
  1. package/package.json +27 -40
  2. package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +7 -7
  3. package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +3 -8
  4. package/src/lib/components/data-table/data-table-bulk-actions.tsx +9 -3
  5. package/src/lib/components/data-table/data-table.tsx +3 -2
  6. package/src/lib/components/ui/accordion.tsx +45 -50
  7. package/src/lib/components/ui/alert-dialog.tsx +93 -122
  8. package/src/lib/components/ui/alert.tsx +48 -54
  9. package/src/lib/components/ui/badge.tsx +29 -37
  10. package/src/lib/components/ui/breadcrumb.tsx +82 -89
  11. package/src/lib/components/ui/button.tsx +51 -52
  12. package/src/lib/components/ui/calendar.tsx +435 -196
  13. package/src/lib/components/ui/card.tsx +33 -78
  14. package/src/lib/components/ui/checkbox.tsx +23 -28
  15. package/src/lib/components/ui/collapsible.tsx +2 -0
  16. package/src/lib/components/ui/command.tsx +114 -159
  17. package/src/lib/components/ui/dialog.tsx +90 -115
  18. package/src/lib/components/ui/dropdown-menu.tsx +170 -207
  19. package/src/lib/components/ui/form.tsx +114 -138
  20. package/src/lib/components/ui/hover-card.tsx +26 -32
  21. package/src/lib/components/ui/input.tsx +15 -17
  22. package/src/lib/components/ui/label.tsx +16 -19
  23. package/src/lib/components/ui/pagination.tsx +87 -108
  24. package/src/lib/components/ui/popover.tsx +28 -36
  25. package/src/lib/components/ui/scroll-area.tsx +40 -48
  26. package/src/lib/components/ui/select.tsx +129 -151
  27. package/src/lib/components/ui/separator.tsx +20 -22
  28. package/src/lib/components/ui/sheet.tsx +91 -110
  29. package/src/lib/components/ui/sidebar.tsx +622 -652
  30. package/src/lib/components/ui/skeleton.tsx +10 -10
  31. package/src/lib/components/ui/sonner.tsx +11 -7
  32. package/src/lib/components/ui/switch.tsx +22 -27
  33. package/src/lib/components/ui/table.tsx +64 -96
  34. package/src/lib/components/ui/tabs.tsx +38 -56
  35. package/src/lib/components/ui/textarea.tsx +14 -14
  36. package/src/lib/components/ui/tooltip.tsx +37 -45
  37. package/src/lib/components/ui/aspect-ratio.tsx +0 -9
  38. package/src/lib/components/ui/avatar.tsx +0 -53
  39. package/src/lib/components/ui/carousel.tsx +0 -241
  40. package/src/lib/components/ui/chart.tsx +0 -351
  41. package/src/lib/components/ui/context-menu.tsx +0 -252
  42. package/src/lib/components/ui/drawer.tsx +0 -133
  43. package/src/lib/components/ui/input-otp.tsx +0 -77
  44. package/src/lib/components/ui/menubar.tsx +0 -274
  45. package/src/lib/components/ui/navigation-menu.tsx +0 -168
  46. package/src/lib/components/ui/progress.tsx +0 -29
  47. package/src/lib/components/ui/radio-group.tsx +0 -45
  48. package/src/lib/components/ui/resizable.tsx +0 -54
  49. package/src/lib/components/ui/slider.tsx +0 -63
  50. package/src/lib/components/ui/toggle-group.tsx +0 -73
  51. package/src/lib/components/ui/toggle.tsx +0 -45
@@ -1,726 +1,696 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { Slot } from "@radix-ui/react-slot"
5
- import { cva, VariantProps } from "class-variance-authority"
6
- import { PanelLeftIcon } from "lucide-react"
7
-
8
- import { useIsMobile } from "@/vdb/hooks/use-mobile"
9
- import { cn } from "@/vdb/lib/utils"
10
- import { Button } from "@/vdb/components/ui/button"
11
- import { Input } from "@/vdb/components/ui/input"
12
- import { Separator } from "@/vdb/components/ui/separator"
13
- import {
14
- Sheet,
15
- SheetContent,
16
- SheetDescription,
17
- SheetHeader,
18
- SheetTitle,
19
- } from "@/vdb/components/ui/sheet"
20
- import { Skeleton } from "@/vdb/components/ui/skeleton"
21
- import {
22
- Tooltip,
23
- TooltipContent,
24
- TooltipProvider,
25
- TooltipTrigger,
26
- } from "@/vdb/components/ui/tooltip"
27
-
28
- const SIDEBAR_COOKIE_NAME = "sidebar_state"
29
- const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
30
- const SIDEBAR_WIDTH = "16rem"
31
- const SIDEBAR_WIDTH_MOBILE = "18rem"
32
- const SIDEBAR_WIDTH_ICON = "3rem"
33
- const SIDEBAR_KEYBOARD_SHORTCUT = "b"
34
-
35
- type SidebarContextProps = {
36
- state: "expanded" | "collapsed"
37
- open: boolean
38
- setOpen: (open: boolean) => void
39
- openMobile: boolean
40
- setOpenMobile: (open: boolean) => void
41
- isMobile: boolean
42
- toggleSidebar: () => void
43
- }
44
-
45
- const SidebarContext = React.createContext<SidebarContextProps | null>(null)
1
+ 'use client';
2
+
3
+ import { Slot } from '@radix-ui/react-slot';
4
+ import { VariantProps, cva } from 'class-variance-authority';
5
+ import { PanelLeftIcon } from 'lucide-react';
6
+ import * as React from 'react';
7
+ import { MouseEvent } from 'react';
8
+
9
+ import { Button } from '@/vdb/components/ui/button.js';
10
+ import { Input } from '@/vdb/components/ui/input.js';
11
+ import { Separator } from '@/vdb/components/ui/separator.js';
12
+ import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@/vdb/components/ui/sheet.js';
13
+ import { Skeleton } from '@/vdb/components/ui/skeleton.js';
14
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/vdb/components/ui/tooltip.js';
15
+ import { useIsMobile } from '@/vdb/hooks/use-mobile.js';
16
+ import { cn } from '@/vdb/lib/utils.js';
17
+
18
+ const SIDEBAR_COOKIE_NAME = 'sidebar_state';
19
+ const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
20
+ const SIDEBAR_WIDTH = '16rem';
21
+ const SIDEBAR_WIDTH_MOBILE = '18rem';
22
+ const SIDEBAR_WIDTH_ICON = '3rem';
23
+ const SIDEBAR_KEYBOARD_SHORTCUT = 'b';
24
+
25
+ type SidebarContext = {
26
+ state: 'expanded' | 'collapsed';
27
+ open: boolean;
28
+ setOpen: (open: boolean) => void;
29
+ openMobile: boolean;
30
+ setOpenMobile: (open: boolean) => void;
31
+ isMobile: boolean;
32
+ toggleSidebar: () => void;
33
+ };
34
+
35
+ const SidebarContext = React.createContext<SidebarContext | null>(null);
46
36
 
47
37
  function useSidebar() {
48
- const context = React.useContext(SidebarContext)
49
- if (!context) {
50
- throw new Error("useSidebar must be used within a SidebarProvider.")
51
- }
38
+ const context = React.useContext(SidebarContext);
39
+ if (!context) {
40
+ throw new Error('useSidebar must be used within a SidebarProvider.');
41
+ }
52
42
 
53
- return context
43
+ return context;
54
44
  }
55
45
 
56
- function SidebarProvider({
57
- defaultOpen = true,
58
- open: openProp,
59
- onOpenChange: setOpenProp,
60
- className,
61
- style,
62
- children,
63
- ...props
64
- }: React.ComponentProps<"div"> & {
65
- defaultOpen?: boolean
66
- open?: boolean
67
- onOpenChange?: (open: boolean) => void
68
- }) {
69
- const isMobile = useIsMobile()
70
- const [openMobile, setOpenMobile] = React.useState(false)
71
-
72
- // This is the internal state of the sidebar.
73
- // We use openProp and setOpenProp for control from outside the component.
74
- const [_open, _setOpen] = React.useState(defaultOpen)
75
- const open = openProp ?? _open
76
- const setOpen = React.useCallback(
77
- (value: boolean | ((value: boolean) => boolean)) => {
78
- const openState = typeof value === "function" ? value(open) : value
79
- if (setOpenProp) {
80
- setOpenProp(openState)
81
- } else {
82
- _setOpen(openState)
83
- }
84
-
85
- // This sets the cookie to keep the sidebar state.
86
- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
46
+ const SidebarProvider = React.forwardRef<
47
+ HTMLDivElement,
48
+ React.ComponentProps<'div'> & {
49
+ defaultOpen?: boolean;
50
+ open?: boolean;
51
+ onOpenChange?: (open: boolean) => void;
52
+ }
53
+ >(
54
+ (
55
+ {
56
+ defaultOpen = true,
57
+ open: openProp,
58
+ onOpenChange: setOpenProp,
59
+ className,
60
+ style,
61
+ children,
62
+ ...props
63
+ },
64
+ ref,
65
+ ) => {
66
+ const isMobile = useIsMobile();
67
+ const [openMobile, setOpenMobile] = React.useState(false);
68
+
69
+ // This is the internal state of the sidebar.
70
+ // We use openProp and setOpenProp for control from outside the component.
71
+ const [_open, _setOpen] = React.useState(defaultOpen);
72
+ const open = openProp ?? _open;
73
+ const setOpen = React.useCallback(
74
+ (value: boolean | ((value: boolean) => boolean)) => {
75
+ const openState = typeof value === 'function' ? value(open) : value;
76
+ if (setOpenProp) {
77
+ setOpenProp(openState);
78
+ } else {
79
+ _setOpen(openState);
80
+ }
81
+
82
+ // This sets the cookie to keep the sidebar state.
83
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
84
+ },
85
+ [setOpenProp, open],
86
+ );
87
+
88
+ // Helper to toggle the sidebar.
89
+ const toggleSidebar = React.useCallback(() => {
90
+ return isMobile ? setOpenMobile(open => !open) : setOpen(open => !open);
91
+ }, [isMobile, setOpen, setOpenMobile]);
92
+
93
+ // Adds a keyboard shortcut to toggle the sidebar.
94
+ React.useEffect(() => {
95
+ const handleKeyDown = (event: KeyboardEvent) => {
96
+ if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
97
+ event.preventDefault();
98
+ toggleSidebar();
99
+ }
100
+ };
101
+
102
+ window.addEventListener('keydown', handleKeyDown);
103
+ return () => window.removeEventListener('keydown', handleKeyDown);
104
+ }, [toggleSidebar]);
105
+
106
+ // We add a state so that we can do data-state="expanded" or "collapsed".
107
+ // This makes it easier to style the sidebar with Tailwind classes.
108
+ const state = open ? 'expanded' : 'collapsed';
109
+
110
+ const contextValue = React.useMemo<SidebarContext>(
111
+ () => ({
112
+ state,
113
+ open,
114
+ setOpen,
115
+ isMobile,
116
+ openMobile,
117
+ setOpenMobile,
118
+ toggleSidebar,
119
+ }),
120
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar],
121
+ );
122
+
123
+ return (
124
+ <SidebarContext.Provider value={contextValue}>
125
+ <TooltipProvider delayDuration={0}>
126
+ <div
127
+ data-slot="sidebar-wrapper"
128
+ style={
129
+ {
130
+ '--sidebar-width': SIDEBAR_WIDTH,
131
+ '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,
132
+ ...style,
133
+ } as React.CSSProperties
134
+ }
135
+ className={cn(
136
+ 'group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full',
137
+ className,
138
+ )}
139
+ ref={ref}
140
+ {...props}
141
+ >
142
+ {children}
143
+ </div>
144
+ </TooltipProvider>
145
+ </SidebarContext.Provider>
146
+ );
87
147
  },
88
- [setOpenProp, open]
89
- )
90
-
91
- // Helper to toggle the sidebar.
92
- const toggleSidebar = React.useCallback(() => {
93
- return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)
94
- }, [isMobile, setOpen, setOpenMobile])
95
-
96
- // Adds a keyboard shortcut to toggle the sidebar.
97
- React.useEffect(() => {
98
- const handleKeyDown = (event: KeyboardEvent) => {
99
- if (
100
- event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
101
- (event.metaKey || event.ctrlKey)
102
- ) {
103
- event.preventDefault()
104
- toggleSidebar()
105
- }
148
+ );
149
+ SidebarProvider.displayName = 'SidebarProvider';
150
+
151
+ function Sidebar({
152
+ side = 'left',
153
+ variant = 'sidebar',
154
+ collapsible = 'offcanvas',
155
+ className,
156
+ children,
157
+ ...props
158
+ }: React.ComponentProps<'div'> & {
159
+ side?: 'left' | 'right';
160
+ variant?: 'sidebar' | 'floating' | 'inset';
161
+ collapsible?: 'offcanvas' | 'icon' | 'none';
162
+ }) {
163
+ const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
164
+
165
+ if (collapsible === 'none') {
166
+ return (
167
+ <div
168
+ data-slot="sidebar"
169
+ className={cn(
170
+ 'bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col',
171
+ className,
172
+ )}
173
+ {...props}
174
+ >
175
+ {children}
176
+ </div>
177
+ );
178
+ }
179
+
180
+ if (isMobile) {
181
+ return (
182
+ <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
183
+ <SheetHeader className="sr-only">
184
+ <SheetTitle>Sidebar</SheetTitle>
185
+ <SheetDescription>Displays the mobile sidebar.</SheetDescription>
186
+ </SheetHeader>
187
+ <SheetContent
188
+ data-sidebar="sidebar"
189
+ data-slot="sidebar"
190
+ data-mobile="true"
191
+ className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
192
+ style={
193
+ {
194
+ '--sidebar-width': SIDEBAR_WIDTH_MOBILE,
195
+ } as React.CSSProperties
196
+ }
197
+ side={side}
198
+ >
199
+ <div className="flex h-full w-full flex-col">{children}</div>
200
+ </SheetContent>
201
+ </Sheet>
202
+ );
106
203
  }
107
204
 
108
- window.addEventListener("keydown", handleKeyDown)
109
- return () => window.removeEventListener("keydown", handleKeyDown)
110
- }, [toggleSidebar])
111
-
112
- // We add a state so that we can do data-state="expanded" or "collapsed".
113
- // This makes it easier to style the sidebar with Tailwind classes.
114
- const state = open ? "expanded" : "collapsed"
115
-
116
- const contextValue = React.useMemo<SidebarContextProps>(
117
- () => ({
118
- state,
119
- open,
120
- setOpen,
121
- isMobile,
122
- openMobile,
123
- setOpenMobile,
124
- toggleSidebar,
125
- }),
126
- [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
127
- )
128
-
129
- return (
130
- <SidebarContext.Provider value={contextValue}>
131
- <TooltipProvider delayDuration={0}>
205
+ return (
132
206
  <div
133
- data-slot="sidebar-wrapper"
134
- style={
135
- {
136
- "--sidebar-width": SIDEBAR_WIDTH,
137
- "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
138
- ...style,
139
- } as React.CSSProperties
140
- }
141
- className={cn(
142
- "group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full",
143
- className
144
- )}
145
- {...props}
207
+ className="group peer text-sidebar-foreground hidden md:block"
208
+ data-state={state}
209
+ data-collapsible={state === 'collapsed' ? collapsible : ''}
210
+ data-variant={variant}
211
+ data-side={side}
212
+ data-slot="sidebar"
146
213
  >
147
- {children}
214
+ {/* This is what handles the sidebar gap on desktop */}
215
+ <div
216
+ className={cn(
217
+ 'relative h-svh w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear',
218
+ 'group-data-[collapsible=offcanvas]:w-0',
219
+ 'group-data-[side=right]:rotate-180',
220
+ variant === 'floating' || variant === 'inset'
221
+ ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]'
222
+ : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',
223
+ )}
224
+ />
225
+ <div
226
+ className={cn(
227
+ 'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex',
228
+ side === 'left'
229
+ ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
230
+ : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
231
+ // Adjust the padding for floating and inset variants.
232
+ variant === 'floating' || variant === 'inset'
233
+ ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
234
+ : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l',
235
+ className,
236
+ )}
237
+ {...props}
238
+ >
239
+ <div
240
+ data-sidebar="sidebar"
241
+ className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
242
+ >
243
+ {children}
244
+ </div>
245
+ </div>
148
246
  </div>
149
- </TooltipProvider>
150
- </SidebarContext.Provider>
151
- )
247
+ );
152
248
  }
153
249
 
154
- function Sidebar({
155
- side = "left",
156
- variant = "sidebar",
157
- collapsible = "offcanvas",
158
- className,
159
- children,
160
- ...props
161
- }: React.ComponentProps<"div"> & {
162
- side?: "left" | "right"
163
- variant?: "sidebar" | "floating" | "inset"
164
- collapsible?: "offcanvas" | "icon" | "none"
165
- }) {
166
- const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
250
+ function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>) {
251
+ const { toggleSidebar } = useSidebar();
167
252
 
168
- if (collapsible === "none") {
169
253
  return (
170
- <div
171
- data-slot="sidebar"
172
- className={cn(
173
- "bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col",
174
- className
175
- )}
176
- {...props}
177
- >
178
- {children}
179
- </div>
180
- )
181
- }
182
-
183
- if (isMobile) {
184
- return (
185
- <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
186
- <SheetContent
187
- data-sidebar="sidebar"
188
- data-slot="sidebar"
189
- data-mobile="true"
190
- className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
191
- style={
192
- {
193
- "--sidebar-width": SIDEBAR_WIDTH_MOBILE,
194
- } as React.CSSProperties
195
- }
196
- side={side}
197
- >
198
- <SheetHeader className="sr-only">
199
- <SheetTitle>Sidebar</SheetTitle>
200
- <SheetDescription>Displays the mobile sidebar.</SheetDescription>
201
- </SheetHeader>
202
- <div className="flex h-full w-full flex-col">{children}</div>
203
- </SheetContent>
204
- </Sheet>
205
- )
206
- }
207
-
208
- return (
209
- <div
210
- className="group peer text-sidebar-foreground hidden md:block"
211
- data-state={state}
212
- data-collapsible={state === "collapsed" ? collapsible : ""}
213
- data-variant={variant}
214
- data-side={side}
215
- data-slot="sidebar"
216
- >
217
- {/* This is what handles the sidebar gap on desktop */}
218
- <div
219
- data-slot="sidebar-gap"
220
- className={cn(
221
- "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
222
- "group-data-[collapsible=offcanvas]:w-0",
223
- "group-data-[side=right]:rotate-180",
224
- variant === "floating" || variant === "inset"
225
- ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
226
- : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
227
- )}
228
- />
229
- <div
230
- data-slot="sidebar-container"
231
- className={cn(
232
- "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
233
- side === "left"
234
- ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
235
- : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
236
- // Adjust the padding for floating and inset variants.
237
- variant === "floating" || variant === "inset"
238
- ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
239
- : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
240
- className
241
- )}
242
- {...props}
243
- >
244
- <div
245
- data-sidebar="sidebar"
246
- data-slot="sidebar-inner"
247
- className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
254
+ <Button
255
+ data-sidebar="trigger"
256
+ data-slot="sidebar-trigger"
257
+ variant="ghost"
258
+ size="icon"
259
+ className={cn('h-7 w-7', className)}
260
+ onClick={(event: MouseEvent<any>) => {
261
+ onClick?.(event);
262
+ toggleSidebar();
263
+ }}
264
+ {...props}
248
265
  >
249
- {children}
250
- </div>
251
- </div>
252
- </div>
253
- )
266
+ <PanelLeftIcon />
267
+ <span className="sr-only">Toggle Sidebar</span>
268
+ </Button>
269
+ );
254
270
  }
255
271
 
256
- function SidebarTrigger({
257
- className,
258
- onClick,
259
- ...props
260
- }: React.ComponentProps<typeof Button>) {
261
- const { toggleSidebar } = useSidebar()
262
-
263
- return (
264
- <Button
265
- data-sidebar="trigger"
266
- data-slot="sidebar-trigger"
267
- variant="ghost"
268
- size="icon"
269
- className={cn("size-7", className)}
270
- onClick={(event) => {
271
- onClick?.(event)
272
- toggleSidebar()
273
- }}
274
- {...props}
275
- >
276
- <PanelLeftIcon />
277
- <span className="sr-only">Toggle Sidebar</span>
278
- </Button>
279
- )
280
- }
272
+ function SidebarRail({ className, ...props }: React.ComponentProps<'button'>) {
273
+ const { toggleSidebar } = useSidebar();
281
274
 
282
- function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
283
- const { toggleSidebar } = useSidebar()
284
-
285
- return (
286
- <button
287
- data-sidebar="rail"
288
- data-slot="sidebar-rail"
289
- aria-label="Toggle Sidebar"
290
- tabIndex={-1}
291
- onClick={toggleSidebar}
292
- title="Toggle Sidebar"
293
- className={cn(
294
- "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex",
295
- "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
296
- "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
297
- "hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full",
298
- "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
299
- "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
300
- className
301
- )}
302
- {...props}
303
- />
304
- )
275
+ return (
276
+ <button
277
+ data-sidebar="rail"
278
+ data-slot="sidebar-rail"
279
+ aria-label="Toggle Sidebar"
280
+ tabIndex={-1}
281
+ onClick={toggleSidebar}
282
+ title="Toggle Sidebar"
283
+ className={cn(
284
+ 'hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex',
285
+ 'in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize',
286
+ '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',
287
+ 'hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full',
288
+ '[[data-side=left][data-collapsible=offcanvas]_&]:-right-2',
289
+ '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',
290
+ className,
291
+ )}
292
+ {...props}
293
+ />
294
+ );
305
295
  }
306
296
 
307
- function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
308
- return (
309
- <main
310
- data-slot="sidebar-inset"
311
- className={cn(
312
- "bg-background relative flex w-full flex-1 flex-col",
313
- "md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
314
- className
315
- )}
316
- {...props}
317
- />
318
- )
297
+ function SidebarInset({ className, ...props }: React.ComponentProps<'main'>) {
298
+ return (
299
+ <main
300
+ data-slot="sidebar-inset"
301
+ className={cn(
302
+ 'bg-background relative flex min-h-svh flex-1 flex-col',
303
+ 'peer-data-[variant=inset]:min-h-[calc(100svh-(--spacing(4)))] md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2',
304
+ className,
305
+ )}
306
+ {...props}
307
+ />
308
+ );
319
309
  }
320
310
 
321
- function SidebarInput({
322
- className,
323
- ...props
324
- }: React.ComponentProps<typeof Input>) {
325
- return (
326
- <Input
327
- data-slot="sidebar-input"
328
- data-sidebar="input"
329
- className={cn("bg-background h-8 w-full shadow-none", className)}
330
- {...props}
331
- />
332
- )
311
+ function SidebarInput({ className, ...props }: React.ComponentProps<typeof Input>) {
312
+ return (
313
+ <Input
314
+ data-slot="sidebar-input"
315
+ data-sidebar="input"
316
+ className={cn('bg-background h-8 w-full shadow-none', className)}
317
+ {...props}
318
+ />
319
+ );
333
320
  }
334
321
 
335
- function SidebarHeader({ className, ...props }: React.ComponentProps<"div">) {
336
- return (
337
- <div
338
- data-slot="sidebar-header"
339
- data-sidebar="header"
340
- className={cn("flex flex-col gap-2 p-2", className)}
341
- {...props}
342
- />
343
- )
322
+ function SidebarHeader({ className, ...props }: React.ComponentProps<'div'>) {
323
+ return (
324
+ <div
325
+ data-slot="sidebar-header"
326
+ data-sidebar="header"
327
+ className={cn('flex flex-col gap-2 p-2', className)}
328
+ {...props}
329
+ />
330
+ );
344
331
  }
345
332
 
346
- function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) {
347
- return (
348
- <div
349
- data-slot="sidebar-footer"
350
- data-sidebar="footer"
351
- className={cn("flex flex-col gap-2 p-2", className)}
352
- {...props}
353
- />
354
- )
333
+ function SidebarFooter({ className, ...props }: React.ComponentProps<'div'>) {
334
+ return (
335
+ <div
336
+ data-slot="sidebar-footer"
337
+ data-sidebar="footer"
338
+ className={cn('flex flex-col gap-2 p-2', className)}
339
+ {...props}
340
+ />
341
+ );
355
342
  }
356
343
 
357
- function SidebarSeparator({
358
- className,
359
- ...props
360
- }: React.ComponentProps<typeof Separator>) {
361
- return (
362
- <Separator
363
- data-slot="sidebar-separator"
364
- data-sidebar="separator"
365
- className={cn("bg-sidebar-border mx-2 w-auto", className)}
366
- {...props}
367
- />
368
- )
344
+ function SidebarSeparator({ className, ...props }: React.ComponentProps<typeof Separator>) {
345
+ return (
346
+ <Separator
347
+ data-slot="sidebar-separator"
348
+ data-sidebar="separator"
349
+ className={cn('bg-sidebar-border mx-2 w-auto', className)}
350
+ {...props}
351
+ />
352
+ );
369
353
  }
370
354
 
371
- function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
372
- return (
373
- <div
374
- data-slot="sidebar-content"
375
- data-sidebar="content"
376
- className={cn(
377
- "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
378
- className
379
- )}
380
- {...props}
381
- />
382
- )
355
+ function SidebarContent({ className, ...props }: React.ComponentProps<'div'>) {
356
+ return (
357
+ <div
358
+ data-slot="sidebar-content"
359
+ data-sidebar="content"
360
+ className={cn(
361
+ 'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',
362
+ className,
363
+ )}
364
+ {...props}
365
+ />
366
+ );
383
367
  }
384
368
 
385
- function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) {
386
- return (
387
- <div
388
- data-slot="sidebar-group"
389
- data-sidebar="group"
390
- className={cn("relative flex w-full min-w-0 flex-col p-2", className)}
391
- {...props}
392
- />
393
- )
369
+ function SidebarGroup({ className, ...props }: React.ComponentProps<'div'>) {
370
+ return (
371
+ <div
372
+ data-slot="sidebar-group"
373
+ data-sidebar="group"
374
+ className={cn('relative flex w-full min-w-0 flex-col p-2', className)}
375
+ {...props}
376
+ />
377
+ );
394
378
  }
395
379
 
396
380
  function SidebarGroupLabel({
397
- className,
398
- asChild = false,
399
- ...props
400
- }: React.ComponentProps<"div"> & { asChild?: boolean }) {
401
- const Comp = asChild ? Slot : "div"
402
-
403
- return (
404
- <Comp
405
- data-slot="sidebar-group-label"
406
- data-sidebar="group-label"
407
- className={cn(
408
- "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
409
- "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
410
- className
411
- )}
412
- {...props}
413
- />
414
- )
381
+ className,
382
+ asChild = false,
383
+ ...props
384
+ }: React.ComponentProps<'div'> & { asChild?: boolean }) {
385
+ const Comp = asChild ? Slot : 'div';
386
+
387
+ return (
388
+ <Comp
389
+ data-slot="sidebar-group-label"
390
+ data-sidebar="group-label"
391
+ className={cn(
392
+ 'text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
393
+ 'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',
394
+ className,
395
+ )}
396
+ {...props}
397
+ />
398
+ );
415
399
  }
416
400
 
417
401
  function SidebarGroupAction({
418
- className,
419
- asChild = false,
420
- ...props
421
- }: React.ComponentProps<"button"> & { asChild?: boolean }) {
422
- const Comp = asChild ? Slot : "button"
423
-
424
- return (
425
- <Comp
426
- data-slot="sidebar-group-action"
427
- data-sidebar="group-action"
428
- className={cn(
429
- "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
430
- // Increases the hit area of the button on mobile.
431
- "after:absolute after:-inset-2 md:after:hidden",
432
- "group-data-[collapsible=icon]:hidden",
433
- className
434
- )}
435
- {...props}
436
- />
437
- )
402
+ className,
403
+ asChild = false,
404
+ ...props
405
+ }: React.ComponentProps<'button'> & { asChild?: boolean }) {
406
+ const Comp = asChild ? Slot : 'button';
407
+
408
+ return (
409
+ <Comp
410
+ data-slot="sidebar-group-action"
411
+ data-sidebar="group-action"
412
+ className={cn(
413
+ 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
414
+ // Increases the hit area of the button on mobile.
415
+ 'after:absolute after:-inset-2 md:after:hidden',
416
+ 'group-data-[collapsible=icon]:hidden',
417
+ className,
418
+ )}
419
+ {...props}
420
+ />
421
+ );
438
422
  }
439
423
 
440
- function SidebarGroupContent({
441
- className,
442
- ...props
443
- }: React.ComponentProps<"div">) {
444
- return (
445
- <div
446
- data-slot="sidebar-group-content"
447
- data-sidebar="group-content"
448
- className={cn("w-full text-sm", className)}
449
- {...props}
450
- />
451
- )
424
+ function SidebarGroupContent({ className, ...props }: React.ComponentProps<'div'>) {
425
+ return (
426
+ <div
427
+ data-slot="sidebar-group-content"
428
+ data-sidebar="group-content"
429
+ className={cn('w-full text-sm', className)}
430
+ {...props}
431
+ />
432
+ );
452
433
  }
453
434
 
454
- function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) {
455
- return (
456
- <ul
457
- data-slot="sidebar-menu"
458
- data-sidebar="menu"
459
- className={cn("flex w-full min-w-0 flex-col gap-1", className)}
460
- {...props}
461
- />
462
- )
435
+ function SidebarMenu({ className, ...props }: React.ComponentProps<'ul'>) {
436
+ return (
437
+ <ul
438
+ data-slot="sidebar-menu"
439
+ data-sidebar="menu"
440
+ className={cn('flex w-full min-w-0 flex-col gap-1', className)}
441
+ {...props}
442
+ />
443
+ );
463
444
  }
464
445
 
465
- function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
466
- return (
467
- <li
468
- data-slot="sidebar-menu-item"
469
- data-sidebar="menu-item"
470
- className={cn("group/menu-item relative", className)}
471
- {...props}
472
- />
473
- )
446
+ function SidebarMenuItem({ className, ...props }: React.ComponentProps<'li'>) {
447
+ return (
448
+ <li
449
+ data-slot="sidebar-menu-item"
450
+ data-sidebar="menu-item"
451
+ className={cn('group/menu-item relative', className)}
452
+ {...props}
453
+ />
454
+ );
474
455
  }
475
456
 
476
457
  const sidebarMenuButtonVariants = cva(
477
- "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden 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-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
478
- {
479
- variants: {
480
- variant: {
481
- default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
482
- outline:
483
- "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))]",
484
- },
485
- size: {
486
- default: "h-8 text-sm",
487
- sm: "h-7 text-xs",
488
- lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!",
489
- },
490
- },
491
- defaultVariants: {
492
- variant: "default",
493
- size: "default",
458
+ 'peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden 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-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
459
+ {
460
+ variants: {
461
+ variant: {
462
+ default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
463
+ outline:
464
+ '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))]',
465
+ },
466
+ size: {
467
+ default: 'h-8 text-sm',
468
+ sm: 'h-7 text-xs',
469
+ lg: 'h-12 text-sm group-data-[collapsible=icon]:p-0!',
470
+ },
471
+ },
472
+ defaultVariants: {
473
+ variant: 'default',
474
+ size: 'default',
475
+ },
494
476
  },
495
- }
496
- )
477
+ );
497
478
 
498
479
  function SidebarMenuButton({
499
- asChild = false,
500
- isActive = false,
501
- variant = "default",
502
- size = "default",
503
- tooltip,
504
- className,
505
- ...props
506
- }: React.ComponentProps<"button"> & {
507
- asChild?: boolean
508
- isActive?: boolean
509
- tooltip?: string | React.ComponentProps<typeof TooltipContent>
480
+ asChild = false,
481
+ isActive = false,
482
+ variant = 'default',
483
+ size = 'default',
484
+ tooltip,
485
+ className,
486
+ ...props
487
+ }: React.ComponentProps<'button'> & {
488
+ asChild?: boolean;
489
+ isActive?: boolean;
490
+ tooltip?: string | React.ComponentProps<typeof TooltipContent>;
510
491
  } & VariantProps<typeof sidebarMenuButtonVariants>) {
511
- const Comp = asChild ? Slot : "button"
512
- const { isMobile, state } = useSidebar()
513
-
514
- const button = (
515
- <Comp
516
- data-slot="sidebar-menu-button"
517
- data-sidebar="menu-button"
518
- data-size={size}
519
- data-active={isActive}
520
- className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
521
- {...props}
522
- />
523
- )
524
-
525
- if (!tooltip) {
526
- return button
527
- }
528
-
529
- if (typeof tooltip === "string") {
530
- tooltip = {
531
- children: tooltip,
492
+ const Comp = asChild ? Slot : 'button';
493
+ const { isMobile, state } = useSidebar();
494
+
495
+ const button = (
496
+ <Comp
497
+ data-slot="sidebar-menu-button"
498
+ data-sidebar="menu-button"
499
+ data-size={size}
500
+ data-active={isActive}
501
+ className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
502
+ {...props}
503
+ />
504
+ );
505
+
506
+ if (!tooltip) {
507
+ return button;
532
508
  }
533
- }
534
-
535
- return (
536
- <Tooltip>
537
- <TooltipTrigger asChild>{button}</TooltipTrigger>
538
- <TooltipContent
539
- side="right"
540
- align="center"
541
- hidden={state !== "collapsed" || isMobile}
542
- {...tooltip}
543
- />
544
- </Tooltip>
545
- )
509
+
510
+ if (typeof tooltip === 'string') {
511
+ tooltip = {
512
+ children: tooltip,
513
+ };
514
+ }
515
+
516
+ return (
517
+ <Tooltip>
518
+ <TooltipTrigger asChild>{button}</TooltipTrigger>
519
+ <TooltipContent
520
+ side="right"
521
+ align="center"
522
+ hidden={state !== 'collapsed' || isMobile}
523
+ {...tooltip}
524
+ />
525
+ </Tooltip>
526
+ );
546
527
  }
547
528
 
548
529
  function SidebarMenuAction({
549
- className,
550
- asChild = false,
551
- showOnHover = false,
552
- ...props
553
- }: React.ComponentProps<"button"> & {
554
- asChild?: boolean
555
- showOnHover?: boolean
530
+ className,
531
+ asChild = false,
532
+ showOnHover = false,
533
+ ...props
534
+ }: React.ComponentProps<'button'> & {
535
+ asChild?: boolean;
536
+ showOnHover?: boolean;
556
537
  }) {
557
- const Comp = asChild ? Slot : "button"
558
-
559
- return (
560
- <Comp
561
- data-slot="sidebar-menu-action"
562
- data-sidebar="menu-action"
563
- className={cn(
564
- "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
565
- // Increases the hit area of the button on mobile.
566
- "after:absolute after:-inset-2 md:after:hidden",
567
- "peer-data-[size=sm]/menu-button:top-1",
568
- "peer-data-[size=default]/menu-button:top-1.5",
569
- "peer-data-[size=lg]/menu-button:top-2.5",
570
- "group-data-[collapsible=icon]:hidden",
571
- showOnHover &&
572
- "peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0",
573
- className
574
- )}
575
- {...props}
576
- />
577
- )
538
+ const Comp = asChild ? Slot : 'button';
539
+
540
+ return (
541
+ <Comp
542
+ data-slot="sidebar-menu-action"
543
+ data-sidebar="menu-action"
544
+ className={cn(
545
+ 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
546
+ // Increases the hit area of the button on mobile.
547
+ 'after:absolute after:-inset-2 md:after:hidden',
548
+ 'peer-data-[size=sm]/menu-button:top-1',
549
+ 'peer-data-[size=default]/menu-button:top-1.5',
550
+ 'peer-data-[size=lg]/menu-button:top-2.5',
551
+ 'group-data-[collapsible=icon]:hidden',
552
+ showOnHover &&
553
+ 'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0',
554
+ className,
555
+ )}
556
+ {...props}
557
+ />
558
+ );
578
559
  }
579
560
 
580
- function SidebarMenuBadge({
581
- className,
582
- ...props
583
- }: React.ComponentProps<"div">) {
584
- return (
585
- <div
586
- data-slot="sidebar-menu-badge"
587
- data-sidebar="menu-badge"
588
- className={cn(
589
- "text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none",
590
- "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
591
- "peer-data-[size=sm]/menu-button:top-1",
592
- "peer-data-[size=default]/menu-button:top-1.5",
593
- "peer-data-[size=lg]/menu-button:top-2.5",
594
- "group-data-[collapsible=icon]:hidden",
595
- className
596
- )}
597
- {...props}
598
- />
599
- )
561
+ function SidebarMenuBadge({ className, ...props }: React.ComponentProps<'div'>) {
562
+ return (
563
+ <div
564
+ data-slot="sidebar-menu-badge"
565
+ data-sidebar="menu-badge"
566
+ className={cn(
567
+ 'text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none',
568
+ 'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',
569
+ 'peer-data-[size=sm]/menu-button:top-1',
570
+ 'peer-data-[size=default]/menu-button:top-1.5',
571
+ 'peer-data-[size=lg]/menu-button:top-2.5',
572
+ 'group-data-[collapsible=icon]:hidden',
573
+ className,
574
+ )}
575
+ {...props}
576
+ />
577
+ );
600
578
  }
601
579
 
602
580
  function SidebarMenuSkeleton({
603
- className,
604
- showIcon = false,
605
- ...props
606
- }: React.ComponentProps<"div"> & {
607
- showIcon?: boolean
581
+ className,
582
+ showIcon = false,
583
+ ...props
584
+ }: React.ComponentProps<'div'> & {
585
+ showIcon?: boolean;
608
586
  }) {
609
- // Random width between 50 to 90%.
610
- const width = React.useMemo(() => {
611
- return `${Math.floor(Math.random() * 40) + 50}%`
612
- }, [])
613
-
614
- return (
615
- <div
616
- data-slot="sidebar-menu-skeleton"
617
- data-sidebar="menu-skeleton"
618
- className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
619
- {...props}
620
- >
621
- {showIcon && (
622
- <Skeleton
623
- className="size-4 rounded-md"
624
- data-sidebar="menu-skeleton-icon"
625
- />
626
- )}
627
- <Skeleton
628
- className="h-4 max-w-(--skeleton-width) flex-1"
629
- data-sidebar="menu-skeleton-text"
630
- style={
631
- {
632
- "--skeleton-width": width,
633
- } as React.CSSProperties
634
- }
635
- />
636
- </div>
637
- )
587
+ // Random width between 50 to 90%.
588
+ const width = React.useMemo(() => {
589
+ return `${Math.floor(Math.random() * 40) + 50}%`;
590
+ }, []);
591
+
592
+ return (
593
+ <div
594
+ data-slot="sidebar-menu-skeleton"
595
+ data-sidebar="menu-skeleton"
596
+ className={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}
597
+ {...props}
598
+ >
599
+ {showIcon && <Skeleton className="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />}
600
+ <Skeleton
601
+ className="h-4 max-w-(--skeleton-width) flex-1"
602
+ data-sidebar="menu-skeleton-text"
603
+ style={
604
+ {
605
+ '--skeleton-width': width,
606
+ } as React.CSSProperties
607
+ }
608
+ />
609
+ </div>
610
+ );
638
611
  }
639
612
 
640
- function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) {
641
- return (
642
- <ul
643
- data-slot="sidebar-menu-sub"
644
- data-sidebar="menu-sub"
645
- className={cn(
646
- "border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5",
647
- "group-data-[collapsible=icon]:hidden",
648
- className
649
- )}
650
- {...props}
651
- />
652
- )
613
+ function SidebarMenuSub({ className, ...props }: React.ComponentProps<'ul'>) {
614
+ return (
615
+ <ul
616
+ data-slot="sidebar-menu-sub"
617
+ data-sidebar="menu-sub"
618
+ className={cn(
619
+ 'border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5',
620
+ 'group-data-[collapsible=icon]:hidden',
621
+ className,
622
+ )}
623
+ {...props}
624
+ />
625
+ );
653
626
  }
654
627
 
655
- function SidebarMenuSubItem({
656
- className,
657
- ...props
658
- }: React.ComponentProps<"li">) {
659
- return (
660
- <li
661
- data-slot="sidebar-menu-sub-item"
662
- data-sidebar="menu-sub-item"
663
- className={cn("group/menu-sub-item relative", className)}
664
- {...props}
665
- />
666
- )
628
+ function SidebarMenuSubItem({ className, ...props }: React.ComponentProps<'li'>) {
629
+ return (
630
+ <li
631
+ data-slot="sidebar-menu-sub-item"
632
+ data-sidebar="menu-sub-item"
633
+ className={cn('group/menu-sub-item relative', className)}
634
+ {...props}
635
+ />
636
+ );
667
637
  }
668
638
 
669
639
  function SidebarMenuSubButton({
670
- asChild = false,
671
- size = "md",
672
- isActive = false,
673
- className,
674
- ...props
675
- }: React.ComponentProps<"a"> & {
676
- asChild?: boolean
677
- size?: "sm" | "md"
678
- isActive?: boolean
640
+ asChild = false,
641
+ size = 'md',
642
+ isActive = false,
643
+ className,
644
+ ...props
645
+ }: React.ComponentProps<'a'> & {
646
+ asChild?: boolean;
647
+ size?: 'sm' | 'md';
648
+ isActive?: boolean;
679
649
  }) {
680
- const Comp = asChild ? Slot : "a"
681
-
682
- return (
683
- <Comp
684
- data-slot="sidebar-menu-sub-button"
685
- data-sidebar="menu-sub-button"
686
- data-size={size}
687
- data-active={isActive}
688
- className={cn(
689
- "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 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",
690
- "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
691
- size === "sm" && "text-xs",
692
- size === "md" && "text-sm",
693
- "group-data-[collapsible=icon]:hidden",
694
- className
695
- )}
696
- {...props}
697
- />
698
- )
650
+ const Comp = asChild ? Slot : 'a';
651
+
652
+ return (
653
+ <Comp
654
+ data-slot="sidebar-menu-sub-button"
655
+ data-sidebar="menu-sub-button"
656
+ data-size={size}
657
+ data-active={isActive}
658
+ className={cn(
659
+ 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 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',
660
+ 'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',
661
+ size === 'sm' && 'text-xs',
662
+ size === 'md' && 'text-sm',
663
+ 'group-data-[collapsible=icon]:hidden',
664
+ className,
665
+ )}
666
+ {...props}
667
+ />
668
+ );
699
669
  }
700
670
 
701
671
  export {
702
- Sidebar,
703
- SidebarContent,
704
- SidebarFooter,
705
- SidebarGroup,
706
- SidebarGroupAction,
707
- SidebarGroupContent,
708
- SidebarGroupLabel,
709
- SidebarHeader,
710
- SidebarInput,
711
- SidebarInset,
712
- SidebarMenu,
713
- SidebarMenuAction,
714
- SidebarMenuBadge,
715
- SidebarMenuButton,
716
- SidebarMenuItem,
717
- SidebarMenuSkeleton,
718
- SidebarMenuSub,
719
- SidebarMenuSubButton,
720
- SidebarMenuSubItem,
721
- SidebarProvider,
722
- SidebarRail,
723
- SidebarSeparator,
724
- SidebarTrigger,
725
- useSidebar,
726
- }
672
+ Sidebar,
673
+ SidebarContent,
674
+ SidebarFooter,
675
+ SidebarGroup,
676
+ SidebarGroupAction,
677
+ SidebarGroupContent,
678
+ SidebarGroupLabel,
679
+ SidebarHeader,
680
+ SidebarInput,
681
+ SidebarInset,
682
+ SidebarMenu,
683
+ SidebarMenuAction,
684
+ SidebarMenuBadge,
685
+ SidebarMenuButton,
686
+ SidebarMenuItem,
687
+ SidebarMenuSkeleton,
688
+ SidebarMenuSub,
689
+ SidebarMenuSubButton,
690
+ SidebarMenuSubItem,
691
+ SidebarProvider,
692
+ SidebarRail,
693
+ SidebarSeparator,
694
+ SidebarTrigger,
695
+ useSidebar,
696
+ };