@betterstart/cli 0.1.28 → 0.1.30

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 (65) hide show
  1. package/dist/{chunk-SAPJG4NO.js → chunk-6JCWMKSY.js} +7 -4
  2. package/dist/{chunk-SAPJG4NO.js.map → chunk-6JCWMKSY.js.map} +1 -1
  3. package/dist/cli.js +749 -866
  4. package/dist/cli.js.map +1 -1
  5. package/dist/drizzle-config-EDKOEZ6G.js +7 -0
  6. package/package.json +1 -1
  7. package/templates/ui/accordion.tsx +73 -42
  8. package/templates/ui/alert-dialog.tsx +155 -90
  9. package/templates/ui/alert.tsx +46 -26
  10. package/templates/ui/aspect-ratio.tsx +4 -2
  11. package/templates/ui/avatar.tsx +92 -43
  12. package/templates/ui/badge.tsx +27 -12
  13. package/templates/ui/breadcrumb.tsx +63 -60
  14. package/templates/ui/button-group.tsx +8 -8
  15. package/templates/ui/button.tsx +44 -26
  16. package/templates/ui/calendar.tsx +43 -34
  17. package/templates/ui/card.tsx +71 -34
  18. package/templates/ui/carousel.tsx +111 -115
  19. package/templates/ui/chart.tsx +197 -207
  20. package/templates/ui/checkbox.tsx +21 -20
  21. package/templates/ui/collapsible.tsx +14 -4
  22. package/templates/ui/combobox.tsx +272 -0
  23. package/templates/ui/command.tsx +139 -101
  24. package/templates/ui/context-menu.tsx +214 -156
  25. package/templates/ui/dialog.tsx +118 -77
  26. package/templates/ui/direction.tsx +20 -0
  27. package/templates/ui/drawer.tsx +89 -69
  28. package/templates/ui/dropdown-menu.tsx +228 -164
  29. package/templates/ui/empty.tsx +8 -5
  30. package/templates/ui/field.tsx +25 -32
  31. package/templates/ui/hover-card.tsx +29 -20
  32. package/templates/ui/input-group.tsx +20 -37
  33. package/templates/ui/input-otp.tsx +57 -42
  34. package/templates/ui/input.tsx +14 -17
  35. package/templates/ui/item.tsx +27 -17
  36. package/templates/ui/kbd.tsx +1 -3
  37. package/templates/ui/label.tsx +14 -14
  38. package/templates/ui/markdown-editor.tsx +1 -1
  39. package/templates/ui/menubar.tsx +220 -188
  40. package/templates/ui/native-select.tsx +42 -0
  41. package/templates/ui/navigation-menu.tsx +130 -90
  42. package/templates/ui/pagination.tsx +88 -73
  43. package/templates/ui/popover.tsx +67 -26
  44. package/templates/ui/progress.tsx +24 -18
  45. package/templates/ui/radio-group.tsx +26 -20
  46. package/templates/ui/resizable.tsx +29 -29
  47. package/templates/ui/scroll-area.tsx +47 -38
  48. package/templates/ui/select.tsx +158 -125
  49. package/templates/ui/separator.tsx +21 -19
  50. package/templates/ui/sheet.tsx +104 -95
  51. package/templates/ui/sidebar.tsx +77 -183
  52. package/templates/ui/skeleton.tsx +8 -2
  53. package/templates/ui/slider.tsx +46 -17
  54. package/templates/ui/sonner.tsx +19 -9
  55. package/templates/ui/spinner.tsx +2 -2
  56. package/templates/ui/switch.tsx +24 -20
  57. package/templates/ui/table.tsx +68 -73
  58. package/templates/ui/tabs.tsx +71 -46
  59. package/templates/ui/textarea.tsx +13 -16
  60. package/templates/ui/toggle-group.tsx +57 -28
  61. package/templates/ui/toggle.tsx +21 -20
  62. package/templates/ui/tooltip.tsx +44 -23
  63. package/dist/drizzle-config-KISB26BA.js +0 -7
  64. package/templates/ui/use-mobile.tsx +0 -19
  65. /package/dist/{drizzle-config-KISB26BA.js.map → drizzle-config-EDKOEZ6G.js.map} +0 -0
@@ -1,17 +1,23 @@
1
1
  'use client'
2
2
 
3
+ import { Button } from '@cms/components/ui/button'
4
+ import { Input } from '@cms/components/ui/input'
5
+ import { Separator } from '@cms/components/ui/separator'
6
+ import {
7
+ Sheet,
8
+ SheetContent,
9
+ SheetDescription,
10
+ SheetHeader,
11
+ SheetTitle
12
+ } from '@cms/components/ui/sheet'
13
+ import { Skeleton } from '@cms/components/ui/skeleton'
14
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@cms/components/ui/tooltip'
15
+ import { useIsMobile } from '@cms/hooks/use-mobile'
3
16
  import { cn } from '@cms/utils/cn'
4
- import { Slot } from '@radix-ui/react-slot'
5
17
  import { cva, type VariantProps } from 'class-variance-authority'
6
- import { PanelLeftIcon } from 'lucide-react'
18
+ import { PanelLeft } from 'lucide-react'
19
+ import { Slot } from 'radix-ui'
7
20
  import * as React from 'react'
8
- import { Button } from './button'
9
- import { Input } from './input'
10
- import { Separator } from './separator'
11
- import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from './sheet'
12
- import { Skeleton } from './skeleton'
13
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip'
14
- import { useIsMobile } from './use-mobile'
15
21
 
16
22
  const SIDEBAR_COOKIE_NAME = 'sidebar_state'
17
23
  const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
@@ -79,7 +85,7 @@ function SidebarProvider({
79
85
  // Helper to toggle the sidebar.
80
86
  const toggleSidebar = React.useCallback(() => {
81
87
  return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)
82
- }, [isMobile, setOpen])
88
+ }, [isMobile, setOpen, setOpenMobile])
83
89
 
84
90
  // Adds a keyboard shortcut to toggle the sidebar.
85
91
  React.useEffect(() => {
@@ -108,32 +114,28 @@ function SidebarProvider({
108
114
  setOpenMobile,
109
115
  toggleSidebar
110
116
  }),
111
- [state, open, setOpen, isMobile, openMobile, toggleSidebar]
117
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
112
118
  )
113
119
 
114
120
  return (
115
121
  <SidebarContext.Provider value={contextValue}>
116
- <TooltipProvider delayDuration={0}>
117
- <div
118
- data-slot="sidebar-wrapper"
119
- style={
120
- {
121
- '--sidebar-width': SIDEBAR_WIDTH,
122
- '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,
123
- ...style
124
- } as React.CSSProperties
125
- }
126
- className={cn(
127
- 'flex min-h-svh w-full',
128
- 'bg-background',
129
- 'group/sidebar-wrapper',
130
- className
131
- )}
132
- {...props}
133
- >
134
- {children}
135
- </div>
136
- </TooltipProvider>
122
+ <div
123
+ data-slot="sidebar-wrapper"
124
+ style={
125
+ {
126
+ '--sidebar-width': SIDEBAR_WIDTH,
127
+ '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,
128
+ ...style
129
+ } as React.CSSProperties
130
+ }
131
+ className={cn(
132
+ 'group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full',
133
+ className
134
+ )}
135
+ {...props}
136
+ >
137
+ {children}
138
+ </div>
137
139
  </SidebarContext.Provider>
138
140
  )
139
141
  }
@@ -144,6 +146,7 @@ function Sidebar({
144
146
  collapsible = 'offcanvas',
145
147
  className,
146
148
  children,
149
+ dir,
147
150
  ...props
148
151
  }: React.ComponentProps<'div'> & {
149
152
  side?: 'left' | 'right'
@@ -157,8 +160,7 @@ function Sidebar({
157
160
  <div
158
161
  data-slot="sidebar"
159
162
  className={cn(
160
- 'flex h-full w-(--sidebar-width) flex-col',
161
- 'bg-sidebar text-default',
163
+ 'bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col',
162
164
  className
163
165
  )}
164
166
  {...props}
@@ -172,10 +174,11 @@ function Sidebar({
172
174
  return (
173
175
  <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
174
176
  <SheetContent
177
+ dir={dir}
175
178
  data-sidebar="sidebar"
176
179
  data-slot="sidebar"
177
180
  data-mobile="true"
178
- className={cn('w-(--sidebar-width) p-0', 'bg-white text-default', '[&>button]:hidden')}
181
+ className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
179
182
  style={
180
183
  {
181
184
  '--sidebar-width': SIDEBAR_WIDTH_MOBILE
@@ -195,7 +198,7 @@ function Sidebar({
195
198
 
196
199
  return (
197
200
  <div
198
- className={cn('hidden', 'bg-background text-sidebar-foreground', 'group peer', 'md:block')}
201
+ className="group peer text-sidebar-foreground hidden md:block"
199
202
  data-state={state}
200
203
  data-collapsible={state === 'collapsed' ? collapsible : ''}
201
204
  data-variant={variant}
@@ -206,9 +209,7 @@ function Sidebar({
206
209
  <div
207
210
  data-slot="sidebar-gap"
208
211
  className={cn(
209
- 'relative w-(--sidebar-width)',
210
- 'bg-transparent',
211
- 'transition-[width] duration-200 ease-linear',
212
+ 'relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear',
212
213
  'group-data-[collapsible=offcanvas]:w-0',
213
214
  'group-data-[side=right]:rotate-180',
214
215
  variant === 'floating' || variant === 'inset'
@@ -218,14 +219,10 @@ function Sidebar({
218
219
  />
219
220
  <div
220
221
  data-slot="sidebar-container"
222
+ data-side={side}
221
223
  className={cn(
222
- 'fixed inset-y-0 z-10 hidden',
223
- 'h-svh w-(--sidebar-width)',
224
- 'transition-[left,right,width] duration-200 ease-linear',
225
- 'md:flex',
226
- side === 'left'
227
- ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
228
- : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
224
+ 'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex',
225
+ // Adjust the padding for floating and inset variants.
229
226
  variant === 'floating' || variant === 'inset'
230
227
  ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
231
228
  : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l',
@@ -236,12 +233,7 @@ function Sidebar({
236
233
  <div
237
234
  data-sidebar="sidebar"
238
235
  data-slot="sidebar-inner"
239
- className={cn(
240
- 'flex h-full w-full flex-col',
241
- 'bg-sidebar text-default',
242
- 'corner-squircle',
243
- 'group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm'
244
- )}
236
+ className="bg-sidebar group-data-[variant=floating]:ring-sidebar-border flex size-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1"
245
237
  >
246
238
  {children}
247
239
  </div>
@@ -258,16 +250,15 @@ function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<t
258
250
  data-sidebar="trigger"
259
251
  data-slot="sidebar-trigger"
260
252
  variant="ghost"
261
- size="icon"
262
- className={cn('size-7', className)}
253
+ size="icon-sm"
254
+ className={cn(className)}
263
255
  onClick={(event) => {
264
256
  onClick?.(event)
265
257
  toggleSidebar()
266
258
  }}
267
259
  {...props}
268
- suppressHydrationWarning
269
260
  >
270
- <PanelLeftIcon />
261
+ <PanelLeft />
271
262
  <span className="sr-only">Toggle Sidebar</span>
272
263
  </Button>
273
264
  )
@@ -285,17 +276,10 @@ function SidebarRail({ className, ...props }: React.ComponentProps<'button'>) {
285
276
  onClick={toggleSidebar}
286
277
  title="Toggle Sidebar"
287
278
  className={cn(
288
- 'absolute inset-y-0 z-20 hidden w-4',
289
- '-translate-x-1/2',
290
- 'transition-all ease-linear',
291
- 'after:absolute after:inset-y-0 after:left-1/2 after:w-[2px]',
292
- 'hover:after:bg-sidebar-border',
293
- 'sm:flex',
294
- 'group-data-[side=left]:-right-4 group-data-[side=right]:left-0',
279
+ 'hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2',
295
280
  'in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize',
296
281
  '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',
297
- 'group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full',
298
- 'hover:group-data-[collapsible=offcanvas]:bg-sidebar',
282
+ 'hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full',
299
283
  '[[data-side=left][data-collapsible=offcanvas]_&]:-right-2',
300
284
  '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',
301
285
  className
@@ -310,11 +294,7 @@ function SidebarInset({ className, ...props }: React.ComponentProps<'main'>) {
310
294
  <main
311
295
  data-slot="sidebar-inset"
312
296
  className={cn(
313
- 'relative flex w-full flex-1 flex-col',
314
- 'bg-background',
315
- 'corner-squircle',
316
- 'md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-2xl md:peer-data-[variant=inset]:shadow-sm',
317
- 'md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2',
297
+ 'bg-background relative flex w-full flex-1 flex-col 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',
318
298
  className
319
299
  )}
320
300
  {...props}
@@ -327,7 +307,7 @@ function SidebarInput({ className, ...props }: React.ComponentProps<typeof Input
327
307
  <Input
328
308
  data-slot="sidebar-input"
329
309
  data-sidebar="input"
330
- className={cn('h-8 w-full', 'bg-background shadow-none', className)}
310
+ className={cn('bg-background h-8 w-full shadow-none', className)}
331
311
  {...props}
332
312
  />
333
313
  )
@@ -349,7 +329,7 @@ function SidebarFooter({ className, ...props }: React.ComponentProps<'div'>) {
349
329
  <div
350
330
  data-slot="sidebar-footer"
351
331
  data-sidebar="footer"
352
- className={cn('flex flex-col gap-2', 'border-t border-border', 'p-2', className)}
332
+ className={cn('flex flex-col gap-2 p-2', className)}
353
333
  {...props}
354
334
  />
355
335
  )
@@ -360,7 +340,7 @@ function SidebarSeparator({ className, ...props }: React.ComponentProps<typeof S
360
340
  <Separator
361
341
  data-slot="sidebar-separator"
362
342
  data-sidebar="separator"
363
- className={cn('mx-2 w-auto', 'bg-sidebar-border', className)}
343
+ className={cn('bg-sidebar-border mx-2 w-auto', className)}
364
344
  {...props}
365
345
  />
366
346
  )
@@ -372,9 +352,7 @@ function SidebarContent({ className, ...props }: React.ComponentProps<'div'>) {
372
352
  data-slot="sidebar-content"
373
353
  data-sidebar="content"
374
354
  className={cn(
375
- 'flex min-h-0 flex-1 flex-col gap-2',
376
- 'overflow-auto',
377
- 'group-data-[collapsible=icon]:overflow-hidden',
355
+ 'no-scrollbar flex min-h-0 flex-1 flex-col gap-0 overflow-auto group-data-[collapsible=icon]:overflow-hidden',
378
356
  className
379
357
  )}
380
358
  {...props}
@@ -398,22 +376,14 @@ function SidebarGroupLabel({
398
376
  asChild = false,
399
377
  ...props
400
378
  }: React.ComponentProps<'div'> & { asChild?: boolean }) {
401
- const Comp = asChild ? Slot : 'div'
379
+ const Comp = asChild ? Slot.Root : 'div'
402
380
 
403
381
  return (
404
382
  <Comp
405
383
  data-slot="sidebar-group-label"
406
384
  data-sidebar="group-label"
407
385
  className={cn(
408
- 'flex h-8 shrink-0 items-center',
409
- 'px-2',
410
- 'text-xs font-medium text-sidebar-foreground/70',
411
- 'rounded-md corner-squircle',
412
- 'ring-sidebar-ring outline-hidden',
413
- 'transition-[margin,opacity] duration-200 ease-linear',
414
- 'focus-visible:ring-2',
415
- '[&>svg]:size-4 [&>svg]:shrink-0',
416
- 'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',
386
+ '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 group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
417
387
  className
418
388
  )}
419
389
  {...props}
@@ -426,25 +396,14 @@ function SidebarGroupAction({
426
396
  asChild = false,
427
397
  ...props
428
398
  }: React.ComponentProps<'button'> & { asChild?: boolean }) {
429
- const Comp = asChild ? Slot : 'button'
399
+ const Comp = asChild ? Slot.Root : 'button'
430
400
 
431
401
  return (
432
402
  <Comp
433
403
  data-slot="sidebar-group-action"
434
404
  data-sidebar="group-action"
435
405
  className={cn(
436
- 'absolute top-3.5 right-3',
437
- 'flex aspect-square w-5 items-center justify-center',
438
- 'p-0',
439
- 'text-sidebar-foreground',
440
- 'rounded-md corner-squircle',
441
- 'ring-sidebar-ring outline-hidden',
442
- 'transition-transform',
443
- 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
444
- 'focus-visible:ring-2',
445
- '[&>svg]:size-4 [&>svg]:shrink-0',
446
- 'after:absolute after:-inset-2 md:after:hidden',
447
- 'group-data-[collapsible=icon]:hidden',
406
+ '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 group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0',
448
407
  className
449
408
  )}
450
409
  {...props}
@@ -468,7 +427,7 @@ function SidebarMenu({ className, ...props }: React.ComponentProps<'ul'>) {
468
427
  <ul
469
428
  data-slot="sidebar-menu"
470
429
  data-sidebar="menu"
471
- className={cn('flex w-full min-w-0 flex-col gap-1', className)}
430
+ className={cn('flex w-full min-w-0 flex-col gap-0', className)}
472
431
  {...props}
473
432
  />
474
433
  )
@@ -479,38 +438,20 @@ function SidebarMenuItem({ className, ...props }: React.ComponentProps<'li'>) {
479
438
  <li
480
439
  data-slot="sidebar-menu-item"
481
440
  data-sidebar="menu-item"
482
- className={cn('relative group/menu-item', className)}
441
+ className={cn('group/menu-item relative', className)}
483
442
  {...props}
484
443
  />
485
444
  )
486
445
  }
487
446
 
488
447
  const sidebarMenuButtonVariants = cva(
489
- [
490
- 'flex w-full items-center gap-2',
491
- 'overflow-hidden p-2',
492
- 'text-left text-sm',
493
- 'rounded-md corner-squircle',
494
- 'ring-sidebar-ring outline-hidden',
495
- 'transition-[width,height,padding]',
496
- 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
497
- 'focus-visible:ring-2',
498
- 'active:bg-sidebar-accent active:text-sidebar-accent-foreground',
499
- 'disabled:pointer-events-none disabled:opacity-50',
500
- 'aria-disabled:pointer-events-none aria-disabled:opacity-50',
501
- 'data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground',
502
- 'data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground',
503
- '[&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
504
- 'group-has-data-[sidebar=menu-action]/menu-item:pr-8',
505
- 'group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2!',
506
- 'peer/menu-button'
507
- ],
448
+ 'ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left text-sm transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button 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',
508
449
  {
509
450
  variants: {
510
451
  variant: {
511
452
  default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
512
453
  outline:
513
- '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))]'
454
+ 'bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]'
514
455
  },
515
456
  size: {
516
457
  default: 'h-8 text-sm',
@@ -538,7 +479,7 @@ function SidebarMenuButton({
538
479
  isActive?: boolean
539
480
  tooltip?: string | React.ComponentProps<typeof TooltipContent>
540
481
  } & VariantProps<typeof sidebarMenuButtonVariants>) {
541
- const Comp = asChild ? Slot : 'button'
482
+ const Comp = asChild ? Slot.Root : 'button'
542
483
  const { isMobile, state } = useSidebar()
543
484
 
544
485
  const button = (
@@ -546,7 +487,7 @@ function SidebarMenuButton({
546
487
  data-slot="sidebar-menu-button"
547
488
  data-sidebar="menu-button"
548
489
  data-size={size}
549
- data-active={isActive}
490
+ data-active={isActive || undefined}
550
491
  className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
551
492
  {...props}
552
493
  />
@@ -584,31 +525,16 @@ function SidebarMenuAction({
584
525
  asChild?: boolean
585
526
  showOnHover?: boolean
586
527
  }) {
587
- const Comp = asChild ? Slot : 'button'
528
+ const Comp = asChild ? Slot.Root : 'button'
588
529
 
589
530
  return (
590
531
  <Comp
591
532
  data-slot="sidebar-menu-action"
592
533
  data-sidebar="menu-action"
593
534
  className={cn(
594
- 'absolute top-1.5 right-1',
595
- 'flex aspect-square w-5 items-center justify-center',
596
- 'p-0',
597
- 'text-sidebar-foreground',
598
- 'rounded-md corner-squircle',
599
- 'ring-sidebar-ring outline-hidden',
600
- 'transition-transform',
601
- 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
602
- 'focus-visible:ring-2',
603
- '[&>svg]:size-4 [&>svg]:shrink-0',
604
- 'peer-hover/menu-button:text-sidebar-accent-foreground',
605
- 'after:absolute after:-inset-2 md:after:hidden',
606
- 'peer-data-[size=sm]/menu-button:top-1',
607
- 'peer-data-[size=default]/menu-button:top-1.5',
608
- 'peer-data-[size=lg]/menu-button:top-2.5',
609
- 'group-data-[collapsible=icon]:hidden',
535
+ '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 group-data-[collapsible=icon]:hidden peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0',
610
536
  showOnHover &&
611
- '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',
537
+ 'peer-data-active/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 aria-expanded:opacity-100 md:opacity-0',
612
538
  className
613
539
  )}
614
540
  {...props}
@@ -622,18 +548,7 @@ function SidebarMenuBadge({ className, ...props }: React.ComponentProps<'div'>)
622
548
  data-slot="sidebar-menu-badge"
623
549
  data-sidebar="menu-badge"
624
550
  className={cn(
625
- 'pointer-events-none absolute right-1',
626
- 'flex h-5 min-w-5 items-center justify-center',
627
- 'px-1',
628
- 'text-xs font-medium tabular-nums text-sidebar-foreground',
629
- 'rounded-md corner-squircle',
630
- 'select-none',
631
- 'peer-hover/menu-button:text-sidebar-accent-foreground',
632
- 'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',
633
- 'peer-data-[size=sm]/menu-button:top-1',
634
- 'peer-data-[size=default]/menu-button:top-1.5',
635
- 'peer-data-[size=lg]/menu-button:top-2.5',
636
- 'group-data-[collapsible=icon]:hidden',
551
+ 'text-sidebar-foreground peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-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 group-data-[collapsible=icon]:hidden peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1',
637
552
  className
638
553
  )}
639
554
  {...props}
@@ -649,20 +564,18 @@ function SidebarMenuSkeleton({
649
564
  showIcon?: boolean
650
565
  }) {
651
566
  // Random width between 50 to 90%.
652
- const width = React.useMemo(() => {
567
+ const [width] = React.useState(() => {
653
568
  return `${Math.floor(Math.random() * 40) + 50}%`
654
- }, [])
569
+ })
655
570
 
656
571
  return (
657
572
  <div
658
573
  data-slot="sidebar-menu-skeleton"
659
574
  data-sidebar="menu-skeleton"
660
- className={cn('flex h-8 items-center gap-2', 'px-2', 'rounded-md corner-squircle', className)}
575
+ className={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}
661
576
  {...props}
662
577
  >
663
- {showIcon && (
664
- <Skeleton className="size-4 rounded-md corner-squircle" data-sidebar="menu-skeleton-icon" />
665
- )}
578
+ {showIcon && <Skeleton className="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />}
666
579
  <Skeleton
667
580
  className="h-4 max-w-(--skeleton-width) flex-1"
668
581
  data-sidebar="menu-skeleton-text"
@@ -682,11 +595,7 @@ function SidebarMenuSub({ className, ...props }: React.ComponentProps<'ul'>) {
682
595
  data-slot="sidebar-menu-sub"
683
596
  data-sidebar="menu-sub"
684
597
  className={cn(
685
- 'mx-3.5 flex min-w-0 flex-col gap-1',
686
- 'px-2.5 py-0.5',
687
- 'translate-x-px',
688
- 'border-l border-sidebar-border',
689
- 'group-data-[collapsible=icon]:hidden',
598
+ '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 group-data-[collapsible=icon]:hidden',
690
599
  className
691
600
  )}
692
601
  {...props}
@@ -699,7 +608,7 @@ function SidebarMenuSubItem({ className, ...props }: React.ComponentProps<'li'>)
699
608
  <li
700
609
  data-slot="sidebar-menu-sub-item"
701
610
  data-sidebar="menu-sub-item"
702
- className={cn('relative group/menu-sub-item', className)}
611
+ className={cn('group/menu-sub-item relative', className)}
703
612
  {...props}
704
613
  />
705
614
  )
@@ -716,31 +625,16 @@ function SidebarMenuSubButton({
716
625
  size?: 'sm' | 'md'
717
626
  isActive?: boolean
718
627
  }) {
719
- const Comp = asChild ? Slot : 'a'
628
+ const Comp = asChild ? Slot.Root : 'a'
720
629
 
721
630
  return (
722
631
  <Comp
723
632
  data-slot="sidebar-menu-sub-button"
724
633
  data-sidebar="menu-sub-button"
725
634
  data-size={size}
726
- data-active={isActive}
635
+ data-active={isActive || undefined}
727
636
  className={cn(
728
- 'flex h-7 min-w-0 items-center gap-2',
729
- 'overflow-hidden px-2',
730
- 'text-sidebar-foreground',
731
- 'rounded-md corner-squircle',
732
- 'ring-sidebar-ring outline-hidden',
733
- '-translate-x-px',
734
- 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
735
- 'focus-visible:ring-2',
736
- 'active:bg-sidebar-accent active:text-sidebar-accent-foreground',
737
- 'disabled:pointer-events-none disabled:opacity-50',
738
- 'aria-disabled:pointer-events-none aria-disabled:opacity-50',
739
- '[&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground',
740
- 'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',
741
- size === 'sm' && 'text-xs',
742
- size === 'md' && 'text-sm',
743
- 'group-data-[collapsible=icon]:hidden',
637
+ '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 data-active:bg-sidebar-accent data-active: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 group-data-[collapsible=icon]:hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-sm data-[size=sm]:text-xs [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
744
638
  className
745
639
  )}
746
640
  {...props}
@@ -1,7 +1,13 @@
1
1
  import { cn } from '@cms/utils/cn'
2
2
 
3
- function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
4
- return <div className={cn('animate-pulse rounded-md bg-primary/10', className)} {...props} />
3
+ function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn('bg-muted animate-pulse rounded-md', className)}
8
+ {...props}
9
+ />
10
+ )
5
11
  }
6
12
 
7
13
  export { Skeleton }
@@ -1,24 +1,53 @@
1
1
  'use client'
2
2
 
3
3
  import { cn } from '@cms/utils/cn'
4
- import * as SliderPrimitive from '@radix-ui/react-slider'
4
+ import { Slider as SliderPrimitive } from 'radix-ui'
5
5
  import * as React from 'react'
6
6
 
7
- const Slider = React.forwardRef<
8
- React.ElementRef<typeof SliderPrimitive.Root>,
9
- React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
10
- >(({ className, ...props }, ref) => (
11
- <SliderPrimitive.Root
12
- ref={ref}
13
- className={cn('relative flex w-full touch-none select-none items-center', className)}
14
- {...props}
15
- >
16
- <SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
17
- <SliderPrimitive.Range className="absolute h-full bg-primary" />
18
- </SliderPrimitive.Track>
19
- <SliderPrimitive.Thumb className="block size-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
20
- </SliderPrimitive.Root>
21
- ))
22
- Slider.displayName = SliderPrimitive.Root.displayName
7
+ function Slider({
8
+ className,
9
+ defaultValue,
10
+ value,
11
+ min = 0,
12
+ max = 100,
13
+ ...props
14
+ }: React.ComponentProps<typeof SliderPrimitive.Root>) {
15
+ const _values = React.useMemo(
16
+ () => (Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max]),
17
+ [value, defaultValue, min, max]
18
+ )
19
+
20
+ return (
21
+ <SliderPrimitive.Root
22
+ data-slot="slider"
23
+ defaultValue={defaultValue}
24
+ value={value}
25
+ min={min}
26
+ max={max}
27
+ className={cn(
28
+ 'relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:min-h-40 data-vertical:w-auto data-vertical:flex-col',
29
+ className
30
+ )}
31
+ {...props}
32
+ >
33
+ <SliderPrimitive.Track
34
+ data-slot="slider-track"
35
+ className="bg-muted relative grow overflow-hidden rounded-full data-horizontal:h-1 data-horizontal:w-full data-vertical:h-full data-vertical:w-1"
36
+ >
37
+ <SliderPrimitive.Range
38
+ data-slot="slider-range"
39
+ className="bg-primary absolute select-none data-horizontal:h-full data-vertical:w-full"
40
+ />
41
+ </SliderPrimitive.Track>
42
+ {Array.from({ length: _values.length }, (_, index) => (
43
+ <SliderPrimitive.Thumb
44
+ data-slot="slider-thumb"
45
+ key={index}
46
+ className="border-ring ring-ring/50 relative block size-3 shrink-0 rounded-full border bg-white transition-[color,box-shadow] select-none after:absolute after:-inset-2 hover:ring-3 focus-visible:ring-3 focus-visible:outline-hidden active:ring-3 disabled:pointer-events-none disabled:opacity-50"
47
+ />
48
+ ))}
49
+ </SliderPrimitive.Root>
50
+ )
51
+ }
23
52
 
24
53
  export { Slider }
@@ -1,9 +1,8 @@
1
1
  'use client'
2
2
 
3
- import { useTheme } from '@cms/hooks/use-cms-theme'
4
- import { Toaster as Sonner } from 'sonner'
5
-
6
- type ToasterProps = React.ComponentProps<typeof Sonner>
3
+ import { CircleCheck, CircleX, Info, LoaderCircle, TriangleAlert } from 'lucide-react'
4
+ import { useTheme } from 'next-themes'
5
+ import { Toaster as Sonner, type ToasterProps } from 'sonner'
7
6
 
8
7
  const Toaster = ({ ...props }: ToasterProps) => {
9
8
  const { theme = 'system' } = useTheme()
@@ -12,13 +11,24 @@ const Toaster = ({ ...props }: ToasterProps) => {
12
11
  <Sonner
13
12
  theme={theme as ToasterProps['theme']}
14
13
  className="toaster group"
14
+ icons={{
15
+ success: <CircleCheck className="size-4" />,
16
+ info: <Info className="size-4" />,
17
+ warning: <TriangleAlert className="size-4" />,
18
+ error: <CircleX className="size-4" />,
19
+ loading: <LoaderCircle className="size-4 animate-spin" />
20
+ }}
21
+ style={
22
+ {
23
+ '--normal-bg': 'var(--popover)',
24
+ '--normal-text': 'var(--popover-foreground)',
25
+ '--normal-border': 'var(--border)',
26
+ '--border-radius': 'var(--radius)'
27
+ } as React.CSSProperties
28
+ }
15
29
  toastOptions={{
16
30
  classNames: {
17
- toast:
18
- 'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg',
19
- description: 'group-[.toast]:text-muted-foreground',
20
- actionButton: 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground',
21
- cancelButton: 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground'
31
+ toast: 'cn-toast'
22
32
  }
23
33
  }}
24
34
  {...props}
@@ -1,9 +1,9 @@
1
1
  import { cn } from '@cms/utils/cn'
2
- import { Loader2Icon } from 'lucide-react'
2
+ import { LoaderCircle } from 'lucide-react'
3
3
 
4
4
  function Spinner({ className, ...props }: React.ComponentProps<'svg'>) {
5
5
  return (
6
- <Loader2Icon
6
+ <LoaderCircle
7
7
  role="status"
8
8
  aria-label="Loading"
9
9
  className={cn('size-4 animate-spin', className)}