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

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 (58) hide show
  1. package/dist/plugin/vite-plugin-vendure-dashboard.js +1 -1
  2. package/package.json +40 -27
  3. package/src/app/routes/_authenticated/_collections/collections.graphql.ts +32 -0
  4. package/src/app/routes/_authenticated/_collections/collections.tsx +153 -133
  5. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +34 -1
  6. package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +430 -0
  7. package/src/app/routes/_authenticated/_collections/components/move-single-collection.tsx +33 -0
  8. package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +8 -3
  9. package/src/lib/components/data-table/data-table.tsx +1 -1
  10. package/src/lib/components/shared/paginated-list-data-table.tsx +1 -1
  11. package/src/lib/components/ui/accordion.tsx +50 -45
  12. package/src/lib/components/ui/alert-dialog.tsx +122 -93
  13. package/src/lib/components/ui/alert.tsx +54 -48
  14. package/src/lib/components/ui/aspect-ratio.tsx +9 -0
  15. package/src/lib/components/ui/avatar.tsx +53 -0
  16. package/src/lib/components/ui/badge.tsx +37 -29
  17. package/src/lib/components/ui/breadcrumb.tsx +89 -82
  18. package/src/lib/components/ui/button.tsx +52 -51
  19. package/src/lib/components/ui/calendar.tsx +196 -435
  20. package/src/lib/components/ui/card.tsx +78 -33
  21. package/src/lib/components/ui/carousel.tsx +241 -0
  22. package/src/lib/components/ui/chart.tsx +351 -0
  23. package/src/lib/components/ui/checkbox.tsx +28 -23
  24. package/src/lib/components/ui/collapsible.tsx +0 -2
  25. package/src/lib/components/ui/command.tsx +159 -114
  26. package/src/lib/components/ui/context-menu.tsx +252 -0
  27. package/src/lib/components/ui/dialog.tsx +115 -90
  28. package/src/lib/components/ui/drawer.tsx +133 -0
  29. package/src/lib/components/ui/dropdown-menu.tsx +207 -170
  30. package/src/lib/components/ui/form.tsx +138 -114
  31. package/src/lib/components/ui/hover-card.tsx +32 -26
  32. package/src/lib/components/ui/input-otp.tsx +77 -0
  33. package/src/lib/components/ui/input.tsx +17 -15
  34. package/src/lib/components/ui/label.tsx +19 -16
  35. package/src/lib/components/ui/menubar.tsx +274 -0
  36. package/src/lib/components/ui/navigation-menu.tsx +168 -0
  37. package/src/lib/components/ui/pagination.tsx +108 -87
  38. package/src/lib/components/ui/popover.tsx +36 -28
  39. package/src/lib/components/ui/progress.tsx +29 -0
  40. package/src/lib/components/ui/radio-group.tsx +45 -0
  41. package/src/lib/components/ui/resizable.tsx +54 -0
  42. package/src/lib/components/ui/scroll-area.tsx +48 -40
  43. package/src/lib/components/ui/select.tsx +151 -129
  44. package/src/lib/components/ui/separator.tsx +22 -20
  45. package/src/lib/components/ui/sheet.tsx +110 -91
  46. package/src/lib/components/ui/sidebar.tsx +652 -622
  47. package/src/lib/components/ui/skeleton.tsx +10 -10
  48. package/src/lib/components/ui/slider.tsx +63 -0
  49. package/src/lib/components/ui/sonner.tsx +7 -11
  50. package/src/lib/components/ui/switch.tsx +27 -22
  51. package/src/lib/components/ui/table.tsx +96 -64
  52. package/src/lib/components/ui/tabs.tsx +56 -38
  53. package/src/lib/components/ui/textarea.tsx +14 -14
  54. package/src/lib/components/ui/toggle-group.tsx +73 -0
  55. package/src/lib/components/ui/toggle.tsx +45 -0
  56. package/src/lib/components/ui/tooltip.tsx +45 -37
  57. package/src/lib/framework/page/list-page.tsx +1 -1
  58. package/vite/vite-plugin-vendure-dashboard.ts +1 -1
@@ -1,696 +1,726 @@
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);
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)
36
46
 
37
47
  function useSidebar() {
38
- const context = React.useContext(SidebarContext);
39
- if (!context) {
40
- throw new Error('useSidebar must be used within a SidebarProvider.');
41
- }
48
+ const context = React.useContext(SidebarContext)
49
+ if (!context) {
50
+ throw new Error("useSidebar must be used within a SidebarProvider.")
51
+ }
42
52
 
43
- return context;
53
+ return context
44
54
  }
45
55
 
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
- );
147
- },
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';
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
162
68
  }) {
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
- );
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}`
87
+ },
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
+ }
203
106
  }
204
107
 
205
- return (
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}>
206
132
  <div
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"
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}
213
146
  >
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>
147
+ {children}
246
148
  </div>
247
- );
149
+ </TooltipProvider>
150
+ </SidebarContext.Provider>
151
+ )
248
152
  }
249
153
 
250
- function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>) {
251
- const { toggleSidebar } = useSidebar();
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()
252
167
 
168
+ if (collapsible === "none") {
253
169
  return (
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}
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"
265
248
  >
266
- <PanelLeftIcon />
267
- <span className="sr-only">Toggle Sidebar</span>
268
- </Button>
269
- );
249
+ {children}
250
+ </div>
251
+ </div>
252
+ </div>
253
+ )
270
254
  }
271
255
 
272
- function SidebarRail({ className, ...props }: React.ComponentProps<'button'>) {
273
- const { toggleSidebar } = useSidebar();
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
+ }
274
281
 
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
- );
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
+ )
295
305
  }
296
306
 
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
- );
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
+ )
309
319
  }
310
320
 
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
- );
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
+ )
320
333
  }
321
334
 
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
- );
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
+ )
331
344
  }
332
345
 
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
- );
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
+ )
342
355
  }
343
356
 
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
- );
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
+ )
353
369
  }
354
370
 
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
- );
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
+ )
367
383
  }
368
384
 
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
- );
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
+ )
378
394
  }
379
395
 
380
396
  function SidebarGroupLabel({
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
- );
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
+ )
399
415
  }
400
416
 
401
417
  function SidebarGroupAction({
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
- );
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
+ )
422
438
  }
423
439
 
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
- );
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
+ )
433
452
  }
434
453
 
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
- );
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
+ )
444
463
  }
445
464
 
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
- );
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
+ )
455
474
  }
456
475
 
457
476
  const sidebarMenuButtonVariants = cva(
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
- },
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",
476
494
  },
477
- );
495
+ }
496
+ )
478
497
 
479
498
  function SidebarMenuButton({
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>;
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>
491
510
  } & VariantProps<typeof sidebarMenuButtonVariants>) {
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;
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,
508
532
  }
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
- );
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
+ )
527
546
  }
528
547
 
529
548
  function SidebarMenuAction({
530
- className,
531
- asChild = false,
532
- showOnHover = false,
533
- ...props
534
- }: React.ComponentProps<'button'> & {
535
- asChild?: boolean;
536
- showOnHover?: boolean;
549
+ className,
550
+ asChild = false,
551
+ showOnHover = false,
552
+ ...props
553
+ }: React.ComponentProps<"button"> & {
554
+ asChild?: boolean
555
+ showOnHover?: boolean
537
556
  }) {
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
- );
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
+ )
559
578
  }
560
579
 
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
- );
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
+ )
578
600
  }
579
601
 
580
602
  function SidebarMenuSkeleton({
581
- className,
582
- showIcon = false,
583
- ...props
584
- }: React.ComponentProps<'div'> & {
585
- showIcon?: boolean;
603
+ className,
604
+ showIcon = false,
605
+ ...props
606
+ }: React.ComponentProps<"div"> & {
607
+ showIcon?: boolean
586
608
  }) {
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
- );
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
+ )
611
638
  }
612
639
 
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
- );
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
+ )
626
653
  }
627
654
 
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
- );
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
+ )
637
667
  }
638
668
 
639
669
  function SidebarMenuSubButton({
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;
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
649
679
  }) {
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
- );
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
+ )
669
699
  }
670
700
 
671
701
  export {
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
- };
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
+ }