@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.
- package/dist/{chunk-SAPJG4NO.js → chunk-6JCWMKSY.js} +7 -4
- package/dist/{chunk-SAPJG4NO.js.map → chunk-6JCWMKSY.js.map} +1 -1
- package/dist/cli.js +749 -866
- package/dist/cli.js.map +1 -1
- package/dist/drizzle-config-EDKOEZ6G.js +7 -0
- package/package.json +1 -1
- package/templates/ui/accordion.tsx +73 -42
- package/templates/ui/alert-dialog.tsx +155 -90
- package/templates/ui/alert.tsx +46 -26
- package/templates/ui/aspect-ratio.tsx +4 -2
- package/templates/ui/avatar.tsx +92 -43
- package/templates/ui/badge.tsx +27 -12
- package/templates/ui/breadcrumb.tsx +63 -60
- package/templates/ui/button-group.tsx +8 -8
- package/templates/ui/button.tsx +44 -26
- package/templates/ui/calendar.tsx +43 -34
- package/templates/ui/card.tsx +71 -34
- package/templates/ui/carousel.tsx +111 -115
- package/templates/ui/chart.tsx +197 -207
- package/templates/ui/checkbox.tsx +21 -20
- package/templates/ui/collapsible.tsx +14 -4
- package/templates/ui/combobox.tsx +272 -0
- package/templates/ui/command.tsx +139 -101
- package/templates/ui/context-menu.tsx +214 -156
- package/templates/ui/dialog.tsx +118 -77
- package/templates/ui/direction.tsx +20 -0
- package/templates/ui/drawer.tsx +89 -69
- package/templates/ui/dropdown-menu.tsx +228 -164
- package/templates/ui/empty.tsx +8 -5
- package/templates/ui/field.tsx +25 -32
- package/templates/ui/hover-card.tsx +29 -20
- package/templates/ui/input-group.tsx +20 -37
- package/templates/ui/input-otp.tsx +57 -42
- package/templates/ui/input.tsx +14 -17
- package/templates/ui/item.tsx +27 -17
- package/templates/ui/kbd.tsx +1 -3
- package/templates/ui/label.tsx +14 -14
- package/templates/ui/markdown-editor.tsx +1 -1
- package/templates/ui/menubar.tsx +220 -188
- package/templates/ui/native-select.tsx +42 -0
- package/templates/ui/navigation-menu.tsx +130 -90
- package/templates/ui/pagination.tsx +88 -73
- package/templates/ui/popover.tsx +67 -26
- package/templates/ui/progress.tsx +24 -18
- package/templates/ui/radio-group.tsx +26 -20
- package/templates/ui/resizable.tsx +29 -29
- package/templates/ui/scroll-area.tsx +47 -38
- package/templates/ui/select.tsx +158 -125
- package/templates/ui/separator.tsx +21 -19
- package/templates/ui/sheet.tsx +104 -95
- package/templates/ui/sidebar.tsx +77 -183
- package/templates/ui/skeleton.tsx +8 -2
- package/templates/ui/slider.tsx +46 -17
- package/templates/ui/sonner.tsx +19 -9
- package/templates/ui/spinner.tsx +2 -2
- package/templates/ui/switch.tsx +24 -20
- package/templates/ui/table.tsx +68 -73
- package/templates/ui/tabs.tsx +71 -46
- package/templates/ui/textarea.tsx +13 -16
- package/templates/ui/toggle-group.tsx +57 -28
- package/templates/ui/toggle.tsx +21 -20
- package/templates/ui/tooltip.tsx +44 -23
- package/dist/drizzle-config-KISB26BA.js +0 -7
- package/templates/ui/use-mobile.tsx +0 -19
- /package/dist/{drizzle-config-KISB26BA.js.map → drizzle-config-EDKOEZ6G.js.map} +0 -0
package/templates/ui/sidebar.tsx
CHANGED
|
@@ -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 {
|
|
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
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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=
|
|
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=
|
|
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
|
-
|
|
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=
|
|
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(
|
|
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
|
-
<
|
|
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
|
|
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
|
|
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',
|
|
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-
|
|
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-
|
|
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('
|
|
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
|
|
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-
|
|
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.
|
|
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
|
|
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('
|
|
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.
|
|
4
|
-
return
|
|
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 }
|
package/templates/ui/slider.tsx
CHANGED
|
@@ -1,24 +1,53 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import { cn } from '@cms/utils/cn'
|
|
4
|
-
import
|
|
4
|
+
import { Slider as SliderPrimitive } from 'radix-ui'
|
|
5
5
|
import * as React from 'react'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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 }
|
package/templates/ui/sonner.tsx
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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}
|
package/templates/ui/spinner.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { cn } from '@cms/utils/cn'
|
|
2
|
-
import {
|
|
2
|
+
import { LoaderCircle } from 'lucide-react'
|
|
3
3
|
|
|
4
4
|
function Spinner({ className, ...props }: React.ComponentProps<'svg'>) {
|
|
5
5
|
return (
|
|
6
|
-
<
|
|
6
|
+
<LoaderCircle
|
|
7
7
|
role="status"
|
|
8
8
|
aria-label="Loading"
|
|
9
9
|
className={cn('size-4 animate-spin', className)}
|